diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index a1b9d65a0..16e0477f0 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,29 +1,28 @@ --- name: "Bug Report" about: "Report a bug" -title: "[STM32 device name]: [_$YourTitle_]" -labels: '' +title: "[STM32 device name]: $YourTitle" +labels: "" --- Thank you for giving feedback to the stlink project. **NOTICE: Please read and follow instructions in #906 before submitting a ticket. -This feature request will be deleted without notice when not enough information is provided! So please ensure that all fields are filled out.** +This bug report will be deleted without notice when not enough information is provided! So please ensure that all fields are filled out.** - [ ] I made serious effort to avoid creating duplicate or nearly similar issue -In order to allow developers and other contributors to isolate and target your respective issue, please take some time to select the check boxes below -and fill out each of the following items appropriate to your specific problem. +In order to allow developers and other contributors to isolate and target your respective issue, please take some time to select the check boxes below and fill out each of the following items appropriate to your specific problem. -- [ ] Programmer/board type: [enter here] (e.g STLink /V1, /V2, /V2-onboard, /V2-clone, /V3) +- [ ] Programmer/board type: [enter here] (e.g STLINK /V1, /V2, /V2-onboard, /V2-clone, /V3) - [ ] Operating system an version: [enter here] (e.g Linux, macOS, Windows) -- [ ] **Stlink tools version** and/or git commit hash: [enter here] (e.g v1.6.1/git-d0416149) -- [ ] Stlink commandline tool name: [enter here] (e.g `st-info`, `st-flash`, `st-util`) +- [ ] **stlink tools version** and/or git commit hash: [enter here] (e.g v1.6.1/git-d0416149) +- [ ] stlink commandline tool name: [enter here] (e.g `st-info`, `st-flash`, `st-trace`, `st-util`) - [ ] Target chip (and board, if applicable): [enter here] (e.g STM32F103C8T6 (NUCLEO-F103RB)) -Futher we kindly ask you to describe the detected problem as detailed as possible and to add debug output if available, by using the following template: +Further we kindly ask you to describe the detected problem as detailed as possible and to add debug output if available, by using the following template: -Commandline-Output: +Commandline output: ``` OUTPUT/ERROR of the commandline tool(s) @@ -33,7 +32,6 @@ Expected/description: `short description of the expected value` - Thank you for your support. The stlink project maintainers diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md index 3de593aa6..ddeb79357 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -1,7 +1,7 @@ --- name: "Feature Request" about: "Suggest an idea for this project" -title: "[feature] [_$YourTitle_]" +title: "[feature] $YourTitle" labels: code/feature-request --- @@ -12,18 +12,17 @@ This feature request will be deleted without notice when not enough information - [ ] I made serious effort to avoid creating duplicate or nearly similar issue -In order to allow developers and other contributors to isolate and target your respective issue, please take some time to select the check boxes below -and fill out each of the following items appropriate to your specific request. +In order to allow developers and other contributors to isolate and target your respective issue, please take some time to select the check boxes below and fill out each of the following items appropriate to your specific request. -- [ ] Programmer/board type: [enter here] (e.g STLink /V1, /V2, /V2-onboard, /V2-clone, /V3) +- [ ] Programmer/board type: [enter here] (e.g STLINK /V1, /V2, /V2-onboard, /V2-clone, /V3) - [ ] Operating system an version: [enter here] (e.g Linux, macOS, Windows) -- [ ] **Stlink tools version** and/or git commit hash: [enter here] (e.g v1.6.1/git-d0416149) -- [ ] Stlink commandline tool name: [enter here] (e.g `st-info`, `st-flash`, `st-util`) +- [ ] **stlink tools version** and/or git commit hash: [enter here] (e.g v1.6.1/git-d0416149) +- [ ] stlink commandline tool name: [enter here] (e.g `st-info`, `st-flash`, `st-trace`, `st-util`) - [ ] Target chip (and board, if applicable): [enter here] (e.g STM32F103C8T6 (NUCLEO-F103RB)) -Futher we kindly ask you to describe the detected problem as detailed as possible and to add debug output if available, by using the following template: +Further we kindly ask you to describe the detected problem as detailed as possible and to add debug output if available, by using the following template: -Commandline-Output: +Commandline output: ``` OUTPUT/ERROR of the commandline tool(s) @@ -33,7 +32,6 @@ Expected/description: `short description of the expected value` - Thank you for your support. The stlink project maintainers diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml new file mode 100644 index 000000000..ef9e5f172 --- /dev/null +++ b/.github/workflows/c-cpp.yml @@ -0,0 +1,466 @@ +name: C/C++ CI + +on: + push: + branches: [master, develop, testing] + pull_request: + branches: [master, develop, testing] + +jobs: + # Linux + + # job_linux_16_04_64_gcc: + # name: ubuntu-16.04 gcc + # runs-on: ubuntu-16.04 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: sudo apt-get install gcc-5 libusb-1.0.0-dev libgtk-3-dev rpm + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + # job_linux_16_04_32_gcc: + # name: ubuntu-16.04 gcc 32-bit + # runs-on: ubuntu-16.04 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: sudo apt-get install gcc-5 libusb-1.0.0-dev libgtk-3-dev rpm + # - name: Set compiler flags + # run: | + # CFLAGS="$CFLAGS -m32" + # CXXFLAGS="$CXXFLAGS -m32" + # LDFLAGS="$LDFLAGS -m32" + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + # job_linux_16_04_64_clang: + # name: ubuntu-16.04 clang + # runs-on: ubuntu-16.04 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: sudo apt-get install clang-3.5 libusb-1.0.0-dev libgtk-3-dev rpm + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + # job_linux_16_04_32_clang: + # name: ubuntu-16.04 clang 32-bit + # runs-on: ubuntu-16.04 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: sudo apt-get install clang-3.5 libusb-1.0.0-dev libgtk-3-dev rpm + # - name: Set compiler flags + # run: | + # CFLAGS="$CFLAGS -m32" + # CXXFLAGS="$CXXFLAGS -m32" + # LDFLAGS="$LDFLAGS -m32" + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + job_linux_18_04_64_gcc: + name: ubuntu-18.04 gcc + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: install dependencies + run: sudo apt-get install gcc-6 libusb-1.0.0-dev libgtk-3-dev rpm + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_linux_18_04_32_gcc: + name: ubuntu-18.04 gcc 32-bit + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: install dependencies + run: sudo apt-get install gcc-6 libusb-1.0.0-dev libgtk-3-dev rpm + - name: Set compiler flags + run: | + CFLAGS="$CFLAGS -m32" + CXXFLAGS="$CXXFLAGS -m32" + LDFLAGS="$LDFLAGS -m32" + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_linux_18_04_64_clang: + name: ubuntu-18.04 clang + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: install dependencies + run: sudo apt-get install clang-10 libusb-1.0.0-dev libgtk-3-dev rpm + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_linux_18_04_32_clang: + name: ubuntu-18.04 clang 32-bit + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get install clang-10 libusb-1.0.0-dev libgtk-3-dev rpm + - name: Set compiler flags + run: | + CFLAGS="$CFLAGS -m32" + CXXFLAGS="$CXXFLAGS -m32" + LDFLAGS="$LDFLAGS -m32" + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_linux_20_04_64_gcc: + name: ubuntu-20.04 gcc + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get install gcc-10 libusb-1.0.0-dev libgtk-3-dev rpm + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_linux_20_04_32_gcc: + name: ubuntu-20.04 gcc 32-bit + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get install gcc-10 libusb-1.0.0-dev libgtk-3-dev rpm + - name: Set compiler flags + run: | + CFLAGS="$CFLAGS -m32" + CXXFLAGS="$CXXFLAGS -m32" + LDFLAGS="$LDFLAGS -m32" + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_linux_20_04_64_clang: + name: ubuntu-20.04 clang + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get install clang-10 libusb-1.0.0-dev libgtk-3-dev rpm + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_linux_20_04_32_clang: + name: ubuntu-20.04 clang 32-bit + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get install clang-10 libusb-1.0.0-dev libgtk-3-dev rpm + - name: Set compiler flags + run: | + CFLAGS="$CFLAGS -m32" + CXXFLAGS="$CXXFLAGS -m32" + LDFLAGS="$LDFLAGS -m32" + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + # macOS + + # job_macos_10_14_64_gcc: + # name: macos-10.14 gcc + # runs-on: macos-10.14 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: brew install gcc libusb gtk+3 + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + # job_macos_10_14_32_gcc: + # name: macos-10.14 gcc 32-bit + # runs-on: macos-10.14 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: brew install gcc libusb gtk+3 + # - name: Set compiler flags + # run: | + # CFLAGS="$CFLAGS -m32" + # CXXFLAGS="$CXXFLAGS -m32" + # LDFLAGS="$LDFLAGS -m32" + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + # job_macos_10_14_64_clang: + # name: macos-10.14 clang + # runs-on: macos-10.14 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: brew install llvm libusb gtk+3 + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + # job_macos_10_14_32_clang: + # name: macos-10.14 clang 32-bit + # runs-on: macos-10.14 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: brew install llvm libusb gtk+3 + # - name: Set compiler flags + # run: | + # CFLAGS="$CFLAGS -m32" + # CXXFLAGS="$CXXFLAGS -m32" + # LDFLAGS="$LDFLAGS -m32" + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + + job_macos_10_15_gcc: + name: macos-10.15 gcc + runs-on: macos-10.15 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: brew install gcc libusb gtk+3 + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + + job_macos_10_15_clang: + name: macos-10.15 clang + runs-on: macos-10.15 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: brew install llvm libusb gtk+3 + - name: make debug + run: sudo make clean && make debug + - name: make test + run: sudo make clean && make test + - name: make release + run: sudo make clean && make release + - name: sudo make install + run: sudo make clean && sudo make install + - name: sudo make package + run: sudo make package + - name: sudo make uninstall + run: sudo make uninstall && sudo make clean + # job_macos_11_gcc: + # name: macos-11.0 gcc + # runs-on: macos-11.0 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: brew install gcc libusb gtk+3 + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean + # job_macos_11_clang: + # name: macos-11.0 clang + # runs-on: macos-11.0 + # steps: + # - uses: actions/checkout@v2 + # - name: Install dependencies + # run: brew install llvm libusb gtk+3 + # - name: make debug + # run: sudo make clean && make debug + # - name: make test + # run: sudo make clean && make test + # - name: make release + # run: sudo make clean && make release + # - name: sudo make install + # run: sudo make clean && sudo make install + # - name: sudo make package + # run: sudo make package + # - name: sudo make uninstall + # run: sudo make uninstall && sudo make clean +# Linux MinGW cross compliation + +# job_linux_20_04_cross: +# name: ubuntu-20.04 mingw64 +# runs-on: ubuntu-20.04 +# steps: +# - uses: actions/checkout@v2 +# - name: Install dependencies +# run: sudo apt-get install gcc-10 libusb-1.0.0-dev libgtk-3-dev rpm mingw-w64 +# - name: Building Release for Windows (x86-64) ... +# run: sudo mkdir -p build-mingw && cd build-mingw && sudo cmake \ +# -DCMAKE_SYSTEM_NAME=Windows \ +# -DTOOLCHAIN_PREFIX=x86_64-w64-mingw32 \ +# -DCMAKE_TOOLCHAIN_FILE=$PWD/../cmake/modules/set_toolchain.cmake \ +# -DCMAKE_INSTALL_PREFIX=$PWD/install $PWD && \ +# sudo make && sudo rm -rf build-mingw && cd - diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..26313ecb5 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,69 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ testing, develop, master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ testing, develop ] + schedule: + - cron: '00 20 * * 1' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: [ 'cpp' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Install dependencies + run: sudo apt-get install gcc-10 libusb-1.0.0-dev libgtk-3-dev rpm + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.gitignore b/.gitignore index a07eed9ca..1a5fd5ab1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ build -build-mingw +build-mingw-32 +build-mingw-64 .project .cmake/ diff --git a/.travis.sh b/.travis.sh index cc0958bf5..e45cd3609 100755 --- a/.travis.sh +++ b/.travis.sh @@ -8,64 +8,41 @@ echo "----" echo "WORK DIR:$DIR" DIR=$PWD -if [ "$TRAVIS_JOB_NAME" == "linux-mingw" ]; then - echo "--> Building Release for Windows (x86-64) ..." - mkdir -p build-mingw && cd build-mingw - echo "-DCMAKE_SYSTEM_NAME=Windows -DTOOLCHAIN_PREFIX=x86_64-w64-mingw32 \ - -DCMAKE_TOOLCHAIN_FILE=$PWD/../cmake/modules/set_toolchain.cmake -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR" +if [ "$TRAVIS_JOB_NAME" == "linux-mingw-64" ]; then + echo "--> Building for Windows (x86-64) ..." + mkdir -p build-mingw && cd build-mingw-64 cmake -DCMAKE_SYSTEM_NAME=Windows -DTOOLCHAIN_PREFIX=x86_64-w64-mingw32 \ -DCMAKE_TOOLCHAIN_FILE=$PWD/../cmake/modules/set_toolchain.cmake -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR - make && rm -rf build-mingw && cd - + make && rm -rf build-mingw-64 && cd - - echo "--> Building Release for Windows (i686) ..." - mkdir -p build-mingw && cd build-mingw - echo "-DCMAKE_SYSTEM_NAME=Windows -DTOOLCHAIN_PREFIX=i686-w64-mingw32 \ - -DCMAKE_TOOLCHAIN_FILE=$PWD/../cmake/modules/set_toolchain.cmake -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR" +elif [ "$TRAVIS_JOB_NAME" == "linux-mingw-32" ]; then + echo "--> Building for Windows (i686) ..." + mkdir -p build-mingw && cd build-mingw-32 cmake -DCMAKE_SYSTEM_NAME=Windows -DTOOLCHAIN_PREFIX=i686-w64-mingw32 \ -DCMAKE_TOOLCHAIN_FILE=$PWD/../cmake/modules/set_toolchain.cmake -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR - make && rm -rf build-mingw && cd - + make && rm -rf build-mingw-32 && cd - elif [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq || true - sudo apt-get install -qq -y --no-install-recommends libgtk-3-dev echo "--> Building Debug..." mkdir -p build/Debug && cd build/Debug - echo "-DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$PWD/install" cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR make && cd - echo "--> Building Release with package..." mkdir -p build/Release && cd build/Release - echo "-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/install" - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR - make package && cd - - -elif [ "$TRAVIS_OS_NAME" == "osx" ]; then - brew install libusb - - echo "--> Building Debug..." - mkdir -p build/Debug && cd build/Debug - echo "-DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$PWD/install" - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR - make && cd - - - echo "--> Building Release with package..." - mkdir -p build/Release && cd build/Release - echo "-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/install" cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/install $DIR make package && cd - else # local test-build echo "--> Building Debug..." mkdir -p build/Debug && cd build/Debug - echo "-DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$PWD/install" cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$PWD/install ../../ make && cd - echo "--> Building Release with package..." mkdir -p build/Release && cd build/Release - echo "-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/install" cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/install ../../ make package && cd - fi diff --git a/.travis.yml b/.travis.yml index fefafbaf1..a733019a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,60 +2,11 @@ language: c jobs: include: - ### 64-bit builds on AMD64 ### - - os: linux - dist: xenial - env: BADGE=linux - compiler: gcc-5 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["gcc-5", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - - os: linux - dist: bionic - env: BADGE=linux - compiler: gcc-6 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["gcc-6", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - - os: linux - dist: focal - env: BADGE=linux - compiler: gcc-10 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["gcc-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - - os: linux - dist: xenial - env: BADGE=linux - compiler: clang - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - - os: linux - dist: bionic - env: BADGE=linux - compiler: clang-10 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["clang-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - - os: linux - dist: focal - env: BADGE=linux - compiler: clang-10 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["clang-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] + ### cross builds on AMD64 ### - ### cross build on AMD64 ### - os: linux dist: focal - env: BADGE=linux-mingw + env: BADGE=linux-mingw-64 name: linux-mingw compiler: gcc-10 addons: @@ -64,90 +15,19 @@ jobs: packages: ["gcc-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm", "mingw-w64"] - ### 32-bit builds on AMD64 ### - - os: linux - dist: xenial - env: BADGE=linux - compiler: gcc-5 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["gcc-5", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - before_install: - - CFLAGS="$CFLAGS -m32"; CXXFLAGS="$CXXFLAGS -m32"; LDFLAGS="$LDFLAGS -m32"; - - os: linux - dist: bionic - env: BADGE=linux - compiler: gcc-6 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["gcc-6", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - before_install: - - CFLAGS="$CFLAGS -m32"; CXXFLAGS="$CXXFLAGS -m32"; LDFLAGS="$LDFLAGS -m32"; - os: linux dist: focal - env: BADGE=linux + env: BADGE=linux-mingw-32 + name: linux-mingw compiler: gcc-10 addons: apt: sources: ["ubuntu-toolchain-r-test"] - packages: ["gcc-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - before_install: - - CFLAGS="$CFLAGS -m32"; CXXFLAGS="$CXXFLAGS -m32"; LDFLAGS="$LDFLAGS -m32"; - - os: linux - dist: xenial - env: BADGE=linux - compiler: clang - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - before_install: - - CFLAGS="$CFLAGS -m32"; CXXFLAGS="$CXXFLAGS -m32"; LDFLAGS="$LDFLAGS -m32"; - - os: linux - dist: bionic - env: BADGE=linux - compiler: clang-10 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["clang-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - before_install: - - CFLAGS="$CFLAGS -m32"; CXXFLAGS="$CXXFLAGS -m32"; LDFLAGS="$LDFLAGS -m32"; - - os: linux - dist: focal - env: BADGE=linux - compiler: clang-10 - addons: - apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["clang-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm"] - before_install: - - CFLAGS="$CFLAGS -m32"; CXXFLAGS="$CXXFLAGS -m32"; LDFLAGS="$LDFLAGS -m32"; - - ### macOS ### - - os: osx - env: BADGE=osx - compiler: gcc - addons: - homebrew: packages: - - gcc - - libusb - - gtk+3 - - os: osx - env: BADGE=osx - compiler: clang - addons: - homebrew: - packages: - - clang - - libusb - - gtk+3 + ["gcc-10", "libusb-1.0.0-dev", "libgtk-3-dev", "rpm", "mingw-w64"] script: - git fetch --tags - printenv - cmake --version - - if [[ "$TRAVIS_OS_NAME" == "linux" ]] || [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.travis.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./.travis.sh; fi diff --git a/.version b/.version index 9c6d6293b..bd8bf882d 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -1.6.1 +1.7.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 912092b65..9f63eca81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,17 @@ -# stlink ChangeLog +# stlink Changelog -# v1.6.2 +# v1.7.0 -Release date: (TBD) +Release date: 2021-04-25 + +This release drops support for the STLINK/V1 programmer on macOS 10.13. Features: +- Extended set of cmd line arguments for st-info and st-util ([#332](https://github.com/stlink-org/stlink/pull/332), [#990](https://github.com/stlink-org/stlink/pull/990), [#1091](https://github.com/stlink-org/stlink/pull/1091), [#1114](https://github.com/stlink-org/stlink/pull/1114)) +- Extended support for STM32H7 & rework of software reset ([#532](https://github.com/stlink-org/stlink/pull/532), [#801](https://github.com/stlink-org/stlink/pull/801), [#868](https://github.com/stlink-org/stlink/pull/868), [#1008](https://github.com/stlink-org/stlink/pull/1008), [#1059](https://github.com/stlink-org/stlink/pull/1059), [#1063](https://github.com/stlink-org/stlink/pull/1063), [#1071](https://github.com/stlink-org/stlink/pull/1071)) - Added support for STM32H742/743/753 ([#671](https://github.com/stlink-org/stlink/pull/671), [#793](https://github.com/stlink-org/stlink/pull/793), [#823](https://github.com/stlink-org/stlink/pull/823), [#998](https://github.com/stlink-org/stlink/pull/998), [#1052](https://github.com/stlink-org/stlink/pull/1052)) +- Official support for STLINK-V3 programmers (commit [#5e0a502](https://github.com/stlink-org/stlink/commit/5e0a502df812495bfa96fa9116a19f1306152b17), [#820](https://github.com/stlink-org/stlink/pull/820), [#1022](https://github.com/stlink-org/stlink/pull/1022), [#1025](https://github.com/stlink-org/stlink/pull/1025)) - Added preliminary support for STM32L5x2 ([#904](https://github.com/stlink-org/stlink/pull/904), [#999](https://github.com/stlink-org/stlink/pull/999)) - Option bytes on the STM32F767 ZIT6 Nucleo-144 ([#968](https://github.com/stlink-org/stlink/pull/968), [#997](https://github.com/stlink-org/stlink/pull/997)) - Use SetConsoleCtrlHandler for Windows ([#1021](https://github.com/stlink-org/stlink/pull/1021)) @@ -14,13 +19,15 @@ Features: - `st-util`: Add specialized memory map for STM32H7 devices ([#1060](https://github.com/stlink-org/stlink/pull/1060)) - Support for STM32F4 option bytes ([#1062](https://github.com/stlink-org/stlink/pull/1062)) - Link for WIN32 & APPLE with stlink-static ([#1069](https://github.com/stlink-org/stlink/pull/1069)) -- Extended support for STM32H7 ([#1059](https://github.com/stlink-org/stlink/pull/1059), [#1063](https://github.com/stlink-org/stlink/pull/1063), [#1071](https://github.com/stlink-org/stlink/pull/1071)) - ITM functionality for STLink/V2 and STM32Fxx chipsets ([#136](https://github.com/stlink-org/stlink/pull/136), [#179](https://github.com/stlink-org/stlink/pull/179), [#815](https://github.com/stlink-org/stlink/pull/815), [#1072](https://github.com/stlink-org/stlink/pull/1072)) - Included ITM functionality for building with MSVC ([#1080](https://github.com/stlink-org/stlink/pull/1080)) +- Update for CI integration (commit [#0eebc9a](https://github.com/stlink-org/stlink/commit/0eebc9a74506e84d5c460ec325ae98064a81885e), [#1118](https://github.com/stlink-org/stlink/pull/1118)) Updates & changes: -- [doc] Added note on `(gdb) run` command (commit [#03793d4](https://github.com/stlink-org/stlink/commit/03793d42b6078344a9ef8ad55f1d5d0fc19e486e), [#276](https://github.com/stlink-org/stlink/pull/276)) +- [doc] Added tutorial section on unknown chip id error (commit [#229c721](https://github.com/stlink-org/stlink/commit/229c721189587760db5509c59b3c02e93e7035c8), [#107](https://github.com/stlink-org/stlink/pull/107), [#568](https://github.com/stlink-org/stlink/pull/568)) +- [doc] Updated documentation on target resetting ([#261](https://github.com/stlink-org/stlink/pull/261), [#533](https://github.com/stlink-org/stlink/pull/533), [#1107](https://github.com/stlink-org/stlink/pull/1107)) +- [doc] Added note on `(gdb) run` command (commit [#03793d4](https://github.com/stlink-org/stlink/commit/03793d42b6078344a9ef8ad55f1d5d0fc19e486e), [#267](https://github.com/stlink-org/stlink/pull/267)) - [doc] `st-flash --reset` parameter (one solution for #356) ([#642](https://github.com/stlink-org/stlink/pull/642)) - [refactoring] General maintenance ([#864](https://github.com/stlink-org/stlink/pull/864), [#976](https://github.com/stlink-org/stlink/pull/976), [#978](https://github.com/stlink-org/stlink/pull/978)) - Imported debian pkg-settings ([#986](https://github.com/stlink-org/stlink/pull/986)) @@ -29,9 +36,14 @@ Updates & changes: - [doc] Added example for output of `st-info --probe` ([#1007](https://github.com/stlink-org/stlink/pull/1007), [#1049](https://github.com/stlink-org/stlink/pull/1049)) - [refactoring] Correctly handle endianness without reference to host platform ([#1081](https://github.com/stlink-org/stlink/pull/1081)) - Check format string for log messages ([#1093](https://github.com/stlink-org/stlink/pull/1093)) +- Removed abort() from stlink-lib ([#1116](https://github.com/stlink-org/stlink/pull/1116)) Fixes: +- Improvements and fixes of the flash loaders, unification of the reset function ([#244](https://github.com/stlink-org/stlink/pull/244), [#382](https://github.com/stlink-org/stlink/pull/382), [#705](https://github.com/stlink-org/stlink/pull/705), [#980](https://github.com/stlink-org/stlink/pull/980), [#995](https://github.com/stlink-org/stlink/pull/995), [#1008](https://github.com/stlink-org/stlink/pull/1008), [#1115](https://github.com/stlink-org/stlink/pull/1115), [#1117](https://github.com/stlink-org/stlink/pull/1117), [#1122](https://github.com/stlink-org/stlink/pull/1122), [#1124](https://github.com/stlink-org/stlink/pull/1124)) +- Flash loader rework ([#356](https://github.com/stlink-org/stlink/pull/356), [#556](https://github.com/stlink-org/stlink/pull/556), [#593](https://github.com/stlink-org/stlink/pull/593), [#597](https://github.com/stlink-org/stlink/pull/597), [#607](https://github.com/stlink-org/stlink/pull/607), [#612](https://github.com/stlink-org/stlink/pull/612), [#638](https://github.com/stlink-org/stlink/pull/638), [#661](https://github.com/stlink-org/stlink/pull/661), [#690](https://github.com/stlink-org/stlink/pull/690), [#807](https://github.com/stlink-org/stlink/pull/807), [#817](https://github.com/stlink-org/stlink/pull/817), [#818](https://github.com/stlink-org/stlink/pull/818), [#854](https://github.com/stlink-org/stlink/pull/854), [#868](https://github.com/stlink-org/stlink/pull/868), [#967](https://github.com/stlink-org/stlink/pull/967), [#979](https://github.com/stlink-org/stlink/pull/979), [#1008](https://github.com/stlink-org/stlink/pull/1008), [#1043](https://github.com/stlink-org/stlink/pull/1043), [#1054](https://github.com/stlink-org/stlink/pull/1054), [#1092](https://github.com/stlink-org/stlink/pull/1092), [#1105](https://github.com/stlink-org/stlink/pull/1105), [#1113](https://github.com/stlink-org/stlink/pull/1113)) +- Fixed old DFU serial number for STLINK programmers ([#417](https://github.com/stlink-org/stlink/pull/417), [#494](https://github.com/stlink-org/stlink/pull/494), [#1106](https://github.com/stlink-org/stlink/pull/1106), [#1121](https://github.com/stlink-org/stlink/pull/1121)) +- Use vl flashloader for all STM32F1 series ([#769](https://github.com/stlink-org/stlink/pull/769), [#1041](https://github.com/stlink-org/stlink/pull/1041), [#1044](https://github.com/stlink-org/stlink/pull/1044)) - [regression] Changed timeout on flash write ([#787](https://github.com/stlink-org/stlink/pull/787), [#981](https://github.com/stlink-org/stlink/pull/981), [#987](https://github.com/stlink-org/stlink/pull/987)) - cmake compile failure with external `CMAKE_MODULE_PATH` set ([#962](https://github.com/stlink-org/stlink/pull/962)) - doc/man: Fixed installation directory ([#970](https://github.com/stlink-org/stlink/pull/970)) @@ -42,13 +54,20 @@ Fixes: - Fixed `connect under reset` for `st-flash` and `st-util` ([#983](https://github.com/stlink-org/stlink/pull/983)) - Fix for `mmap() size_t overflow` in `st-flash` ([#988](https://github.com/stlink-org/stlink/pull/988), [#989](https://github.com/stlink-org/stlink/pull/989)) - [regression] `stlink-gui` installation issue on Ubuntu-18.04 ([#1001](https://github.com/stlink-org/stlink/pull/1001), [#1004](https://github.com/stlink-org/stlink/pull/1004), [#1006](https://github.com/stlink-org/stlink/pull/1006)) -- `st-util`: wrong register values passed to `gdb` (STLink/V2) ([#1002](https://github.com/stlink-org/stlink/pull/1002), [#1011](https://github.com/stlink-org/stlink/pull/1011), [#1026](https://github.com/stlink-org/stlink/pull/1026), [#1027](https://github.com/stlink-org/stlink/pull/1027)) +- `st-util`: wrong register values passed to `gdb` (STLink/V2) ([#1002](https://github.com/stlink-org/stlink/pull/1002), [#1011](https://github.com/stlink-org/stlink/pull/1011), [#1026](https://github.com/stlink-org/stlink/pull/1026), [#1027](https://github.com/stlink-org/stlink/pull/1027), [#1038](https://github.com/stlink-org/stlink/pull/1038), [#1064](https://github.com/stlink-org/stlink/pull/1064), [#1065](https://github.com/stlink-org/stlink/pull/1065)) +- GDB: Fixed problems with target description ([#1013](https://github.com/stlink-org/stlink/pull/1013), [#1088](https://github.com/stlink-org/stlink/pull/1088), [#1109](https://github.com/stlink-org/stlink/pull/1109)) - [doc] Fixed wrong path for `rules.d` folder ([#1020](https://github.com/stlink-org/stlink/pull/1020)) -- Use vl flashloader for all STM32F1 series ([#1041](https://github.com/stlink-org/stlink/pull/1041), [#1044](https://github.com/stlink-org/stlink/pull/1044)) +- Fixed support for STLINK/V1 programmer ([#1045](https://github.com/stlink-org/stlink/pull/1045), [#1105](https://github.com/stlink-org/stlink/pull/1105)) +- st-util v1.6.1 does not recognize option --freq (commit [#e576768](https://github.com/stlink-org/stlink/commit/e5767681f14de9851aa970a9299930ca68b2ed92), [#1055](https://github.com/stlink-org/stlink/pull/1055)) - Fixed `gettimeofday` for MSVC ([#1074](https://github.com/stlink-org/stlink/pull/1074)) - Bugfixes for compilation with clang ([#1076](https://github.com/stlink-org/stlink/pull/1076), [#1078](https://github.com/stlink-org/stlink/pull/1078)) - Fixed compilation with GCC 11 ([#1077](https://github.com/stlink-org/stlink/pull/1077)) - [regression] Flash_loader: increased wait rounds for slow boards ([#1085](https://github.com/stlink-org/stlink/pull/1085)) +- Fixed support for writing option bytes ([#1102](https://github.com/stlink-org/stlink/pull/1102), [#1128](https://github.com/stlink-org/stlink/pull/1128)) +- [doc] Corrected spelling mistake in bug report template ([#1103](https://github.com/stlink-org/stlink/pull/1103)) +- Fixed STM32WB55 reading DEBUG IDCODE from the wrong address ([#1100](https://github.com/stlink-org/stlink/pull/1100), [#1101](https://github.com/stlink-org/stlink/pull/1101)) +- Applied missing changes to tests ([#1119](https://github.com/stlink-org/stlink/pull/1119)) +- Improvements for Chip_ID read ([#1008](https://github.com/stlink-org/stlink/pull/1008), [#1120](https://github.com/stlink-org/stlink/pull/1120)) # v1.6.1 @@ -58,7 +77,7 @@ This release drops support for some older operating systems. Check project READM Features: -- Basic compatibility for STLink/V3 programmer ([#271](https://github.com/stlink-org/stlink/pull/271), [#863](https://github.com/stlink-org/stlink/pull/863), [#954](https://github.com/stlink-org/stlink/pull/954)) +- Basic compatibility for STLink/V3 programmer ([#271](https://github.com/stlink-org/stlink/pull/271), [#863](https://github.com/stlink-org/stlink/pull/863), [#954](https://github.com/stlink-org/stlink/pull/954), [#1023](https://github.com/stlink-org/stlink/pull/1023)) - Added support for JTAG command API v2 & distinguish protocol versions v1 and v2 - Compatibility with the STLink/V3 firmware which dropped support for the previous API v1 - As of firmware version J11 the STLink/V1 programmer supports API v2 commands as well @@ -146,6 +165,7 @@ Fixes: - Set static link for `libssp` (stack-smashing protection) ([#960](https://github.com/stlink-org/stlink/pull/960), [#961](https://github.com/stlink-org/stlink/pull/961)) - Fixed udev rules installing to wrong directory ([#966](https://github.com/stlink-org/stlink/pull/966)) - Fixed formatting for options display in `st-flash` & `st-info` (commits [#c783d0e](https://github.com/stlink-org/stlink/commit/c783d0e777ccc83a7a8be26a4f4d3414e0478560) and [#562cd24](https://github.com/stlink-org/stlink/commit/562cd2496e696dbd22950925866aac662d81ee5f)) +- Fixed reading of chip ID on Cortex-M0+ core ([#1125](https://github.com/stlink-org/stlink/pull/1125), [#1126](https://github.com/stlink-org/stlink/pull/1126), [#1133](https://github.com/stlink-org/stlink/pull/1133)) # v1.6.0 @@ -172,8 +192,8 @@ Major changes and added features: Updates and fixes: -- Fixed `unkown chip id`, piped output and `st-util -v` ([#107](https://github.com/stlink-org/stlink/pull/107), [#665](https://github.com/stlink-org/stlink/pull/665), [#763](https://github.com/stlink-org/stlink/pull/763)) - Fixed an issue with versioning stuck at 1.4.0 for versions cloned with git ([#563](https://github.com/stlink-org/stlink/pull/563), [#762](https://github.com/stlink-org/stlink/pull/762), [#772](https://github.com/stlink-org/stlink/pull/772)) +- Fixed `unkown chip id`, piped output and `st-util -v` ([#665](https://github.com/stlink-org/stlink/pull/665), [#763](https://github.com/stlink-org/stlink/pull/763)) - Updated STM32F3xx chip ID that covers a few different devices ([#685](https://github.com/stlink-org/stlink/pull/685), [#758](https://github.com/stlink-org/stlink/pull/758)) - Made udev rules and modprobe conf installation optional ([#741](https://github.com/stlink-org/stlink/pull/741)) - Fixed case when `__FILE__` doesn't contain either `/` nor `\\` ([#745](https://github.com/stlink-org/stlink/pull/745)) @@ -205,7 +225,7 @@ Release date: 2018-09-13 Major changes and added features: -- Added reset through `AIRCR` ([#540](https://github.com/stlink-org/stlink/pull/540), [#712](https://github.com/stlink-org/stlink/pull/712)) +- Added reset through `AIRCR` ([#254](https://github.com/stlink-org/stlink/pull/254), [#540](https://github.com/stlink-org/stlink/pull/540), [#712](https://github.com/stlink-org/stlink/pull/712)) - Added creation of icons for `.desktop` file ([#684](https://github.com/stlink-org/stlink/pull/684), [#708](https://github.com/stlink-org/stlink/pull/708)) - Added desktop file for linux ([#688](https://github.com/stlink-org/stlink/pull/688)) - Added button to export STM32 flash memory to a file ([#691](https://github.com/stlink-org/stlink/pull/691)) @@ -268,7 +288,6 @@ Major changes and added features: Updates and fixes: -- Fixed gdb-server: STM32L0xx has no `FP_CTRL` register for breakpoints ([#273](https://github.com/stlink-org/stlink/pull/273)) - Added `--flash=n[k][m]` command line option to override device model ([#305](https://github.com/stlink-org/stlink/pull/305), [#516](https://github.com/stlink-org/stlink/pull/516), [#576](https://github.com/stlink-org/stlink/pull/576)) - Updated `libusb` to 1.0.21 for Windows ([#562](https://github.com/stlink-org/stlink/pull/562)) - Fixed low-voltage flashing on STM32F7 devices ([#566](https://github.com/stlink-org/stlink/pull/566), [#567](https://github.com/stlink-org/stlink/pull/567)) @@ -313,11 +332,11 @@ Major changes and added features: - Added manpages (generated with `pandoc` from Markdown) ([#208](https://github.com/stlink-org/stlink/pull/208), [#464](https://github.com/stlink-org/stlink/pull/464), [#466](https://github.com/stlink-org/stlink/pull/466), [#467](https://github.com/stlink-org/stlink/pull/467)) - Removal of undocumented `st-term` utility, which is now replaced by `st-util` ARM semihosting feature ([#228](https://github.com/stlink-org/stlink/pull/228), [#507](https://github.com/stlink-org/stlink/pull/507), commit [#3fd0f09](https://github.com/stlink-org/stlink/commit/3fd0f099782506532198473b24f643a3f68d5ff9)) - Support serial numbers argument for `st-util` and `st-flash` to probe and control multiple connected programmers ([#318](https://github.com/stlink-org/stlink/pull/318), [#398](https://github.com/stlink-org/stlink/pull/398), [#541](https://github.com/stlink-org/stlink/pull/541)) +- Added 'k' (kill) command to gdb-server, which resets the connection ([#358](https://github.com/stlink-org/stlink/pull/358), [#525](https://github.com/stlink-org/stlink/pull/525), [#527](https://github.com/stlink-org/stlink/pull/527), [#528](https://github.com/stlink-org/stlink/pull/528)) - Merge `st-probe` tool into `st-info` ([#398](https://github.com/stlink-org/stlink/pull/398)) - Added support for native debian packaging ([#444](https://github.com/stlink-org/stlink/pull/444), [#472](https://github.com/stlink-org/stlink/pull/472), [#473](https://github.com/stlink-org/stlink/pull/473), [#482](https://github.com/stlink-org/stlink/pull/482), [#483](https://github.com/stlink-org/stlink/pull/483), [#484](https://github.com/stlink-org/stlink/pull/484), [#485](https://github.com/stlink-org/stlink/pull/485)) - Rewritten commandline parsing for `st-flash` ([#459](https://github.com/stlink-org/stlink/pull/459)) - Added `--reset` command to `st-flash` ([#505](https://github.com/stlink-org/stlink/pull/505)) -- st-util should detect when USB commands fail ([#525](https://github.com/stlink-org/stlink/pull/525), [#527](https://github.com/stlink-org/stlink/pull/527), [#528](https://github.com/stlink-org/stlink/pull/528)) Chip support added for: @@ -333,12 +352,12 @@ Chip support added for: Updates and fixes: +- Do a JTAG reset prior to reading CPU information when processor is in deep sleep ([#291](https://github.com/stlink-org/stlink/pull/291), [#428](https://github.com/stlink-org/stlink/pull/428), [#430](https://github.com/stlink-org/stlink/pull/430), [#451](https://github.com/stlink-org/stlink/pull/451)) - Fixed `unaligned addr or size` when trying to write a program in RAM ([#323](https://github.com/stlink-org/stlink/pull/323)) - Fixed flashing on `STM32_F3_SMALL` ([#325](https://github.com/stlink-org/stlink/pull/325)) - Fixed STM32L-problem with flash loader ([#390](https://github.com/stlink-org/stlink/pull/390), [#407](https://github.com/stlink-org/stlink/pull/407), [#408](https://github.com/stlink-org/stlink/pull/408)) - Don't read the target voltage on startup, because it crashes STM32F100 ([#423](https://github.com/stlink-org/stlink/pull/423), [#424](https://github.com/stlink-org/stlink/pull/424)) - Added a useful error message instead of `[!] send_recv` ([#425](https://github.com/stlink-org/stlink/pull/425), [#426](https://github.com/stlink-org/stlink/pull/426)) -- Do a JTAG reset prior to reading CPU information when processor is in deep sleep ([#428](https://github.com/stlink-org/stlink/pull/428), [#430](https://github.com/stlink-org/stlink/pull/430), [#451](https://github.com/stlink-org/stlink/pull/451)) - Fixed STM32F030 erase error ([#442](https://github.com/stlink-org/stlink/pull/442)) - Fixed memory map for STM32F7xx ([#453](https://github.com/stlink-org/stlink/pull/453), [#456](https://github.com/stlink-org/stlink/pull/456)) - Redesign of `st-flash` commandline options parsing ([#459](https://github.com/stlink-org/stlink/pull/459)) @@ -378,10 +397,15 @@ Updates and fixes: - Fixed STM32F2xx memory map (Nicolas Schodet) - Memory map for STM32F42xxx and STM32F43xxx devices (Craig Lilley) - Stm32l0x flash loader (Robin Kreis) -- Use libusb synchronous api ([#194](https://github.com/stlink-org/stlink/pull/194), [#374](https://github.com/stlink-org/stlink/pull/374)) +- Modified determination of erased byte pattern when flashing ([#193](https://github.com/stlink-org/stlink/pull/193), [#377](https://github.com/stlink-org/stlink/pull/377)) +- Use libusb synchronous api ([#194](https://github.com/stlink-org/stlink/pull/194), [#225](https://github.com/stlink-org/stlink/pull/225), [#374](https://github.com/stlink-org/stlink/pull/374)) - Fixed segfault when programmer is already busy and `NULL` pointers are in the list ([#256](https://github.com/stlink-org/stlink/pull/256), [#394](https://github.com/stlink-org/stlink/pull/394)) +- Fixed gdb-server: Cortex M0 chips have no `FP_CTRL` register for breakpoints ([#266](https://github.com/stlink-org/stlink/pull/266), [#273](https://github.com/stlink-org/stlink/pull/273), [#341](https://github.com/stlink-org/stlink/pull/341)) +- Fixed issue where "unknown chip id!" was seen every other time ([#352](https://github.com/stlink-org/stlink/pull/352), [#367](https://github.com/stlink-org/stlink/pull/367), [#381](https://github.com/stlink-org/stlink/pull/381)) - Send F4 memory-map and features for STM32F429 ([#188](https://github.com/stlink-org/stlink/pull/188), [#196](https://github.com/stlink-org/stlink/pull/196), [#250](https://github.com/stlink-org/stlink/pull/250), [#251](https://github.com/stlink-org/stlink/pull/251)) (Release v1.1.0) - Added AHB3 Peripherals definition for STM32F4 ([#218](https://github.com/stlink-org/stlink/pull/218), [#288](https://github.com/stlink-org/stlink/pull/288)) (Release v1.1.0) +- Reset: st-flash does not work when CPU is in sleep mode ([#62](https://github.com/stlink-org/stlink/pull/62)) (Release v1.0.0) +- Ensure USB device search succeeds if the matched device is at index 0 ([#126](https://github.com/stlink-org/stlink/pull/126), [#151](https://github.com/stlink-org/stlink/pull/151)) (Release v1.0.0) - Corrected flash size register address for STM32F2 devices ([#278](https://github.com/stlink-org/stlink/pull/278)) (Release v1.0.0) Chip support added for: diff --git a/README.md b/README.md index 3799f46d2..600879580 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,55 @@ -Open source version of the STMicroelectronics STlink Tools -========================================================== +# Open source version of the STMicroelectronics STlink Tools [![BSD licensed](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/hyperium/hyper/master/LICENSE) [![GitHub release](https://img.shields.io/github/release/stlink-org/stlink.svg)](https://github.com/stlink-org/stlink/releases/latest) [![Downloads](https://img.shields.io/github/downloads/stlink-org/stlink/total)](https://github.com/stlink-org/stlink/releases/latest) -![GitHub commits](https://img.shields.io/github/commits-since/stlink-org/stlink/v1.6.1/develop) +![GitHub commits](https://img.shields.io/github/commits-since/stlink-org/stlink/v1.7.0/develop) ![GitHub activity](https://img.shields.io/github/commit-activity/m/stlink-org/stlink) ![GitHub contributors](https://img.shields.io/github/contributors/stlink-org/stlink) +[![CodeQL](https://github.com/stlink-org/stlink/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/stlink-org/stlink/actions/workflows/codeql-analysis.yml) +[![C/C++ CI](https://github.com/stlink-org/stlink/actions/workflows/c-cpp.yml/badge.svg?branch=testing)](https://github.com/stlink-org/stlink/actions/workflows/c-cpp.yml) [![Linux Status](https://img.shields.io/travis/stlink-org/stlink/master?env=BADGE=linux&label=linux)](https://travis-ci.org/stlink-org/stlink) [![macOS Status](https://img.shields.io/travis/stlink-org/stlink/master?env=BADGE=osx&label=osx)](https://travis-ci.org/stlink-org/stlink) Recent new features and bugfixes can be found in the [Changelog](CHANGELOG.md) of this software project. - #### License The stlink library and tools are licensed under the **[BSD-3 License](LICENSE.md)**. - ## Introduction -STLink is an open source toolset to program and debug STM32 devices and boards manufactured by STMicroelectronics. +stlink is an open source toolset to program and debug STM32 devices and boards manufactured by STMicroelectronics. It supports several so called STLINK programmer boards (and clones thereof) which use a microcontroller chip to translate commands from USB to JTAG/SWD. There are four generations available on the market which are _all_ supported by this toolset: -* **STLINK/v1** _[obsolete as of 21-11-2019, continued support by this toolset] *)_ +- **STLINK/V1** _[obsolete as of 21-11-2019, continued support by this toolset] \*)_ - transport layer: SCSI passthru commands over USB - - stand-alone programmer and present on STM32VL Discovery boards -* **STLINK/v2** + - stand-alone programmer + - on-board on STM32VL Discovery boards +- **STLINK/V2** - transport layer: raw USB commands - - stand-alone programmer and present on STM32L Discovery and Nucleo boards -* **STLINK/v2-1** + - stand-alone programmer + - on-board on STM32L Discovery and STM32 Nucleo boards +- **STLINK/V2-1** - transport layer: raw USB commands - - present on some STM32 Nucleo boards -* **STLINK/v3** + - on-board on some STM32 Nucleo boards +- **STLINK-V3** - transport layer: raw USB commands - - stand-alone programmer + - stand-alone programmer (STLINK-V3SET, STLINK-V3MINI, STLINK-V3MODS) + - on-board on some STM32 Nucleo boards (STLINK-V3E) -_*)_ **Note: Support on macOS is limited to 10.14 - 10.15. Any later versions are no longer compatible with the STLINK/v1 due to technical reasons.** +_\*)_ **Note: Support for the STLINK/V1 on macOS is limited to 10.14 - 10.15. Due to the deprecation and removal of macOS Kernel Extensions (KEXT) there will be no support for this programmer on macOS 11 or any later version.** On the user level there is no difference in handling or operation between these different revisions. The STlink toolset includes: -* `st-info` - a programmer and chip information tool -* `st-flash` - a flash manipulation tool -* `st-util` - a GDB server (supported in Visual Studio Code / VSCodium via the [Cortex-Debug](https://github.com/Marus/cortex-debug) plugin) -* `stlink-lib` - a communication library -* `stlink-gui` - a GUI-Interface _[optional]_ - +- `st-info` - a programmer and chip information tool +- `st-flash` - a flash manipulation tool +- `st-trace` - a logging tool to record information on execution +- `st-util` - a GDB server (supported in Visual Studio Code / VSCodium via the [Cortex-Debug](https://github.com/Marus/cortex-debug) plugin) +- `stlink-lib` - a communication library +- `stlink-gui` - a GUI-Interface _[optional]_ ## Supported operating systems and hardware combinations @@ -55,21 +57,16 @@ Currently known working combinations of programmers and targets are listed in [d Supported operating systems are listed in [version_support.md](doc/version_support.md). -The `stlink` toolset continues to maintain backwards compatibility with the **STLINK/v1** programmer.
-Please note that on macOS this support is limited to versions 10.13 - 10.15. - - ## Tutorial & HOWTO Our [tutorial](doc/tutorial.md) may help you along with some advanced tasks and additional info. - ## Installation **Windows**: As of Release v1.6.1 stand-alone Windows binaries are made available (again) on the release page of the project. -Please ensure to select the correct version for your system (i686 or x86_64). The archive file can be unzipped to any desired location as it does not contain any hardcoded paths. However we suggest to move the unzipped application folder to `C:\Program Files\` on 32-bit systems and to `C:\Program Files (x86)\` on 64-bit systems (the toolset is a 32-bit). +Please ensure to select the correct version for your system (i686 or x86_64). The archive file can be unzipped to any desired location as it does not contain any hardcoded paths. However we suggest to move the unzipped application folder to `C:\Program Files\` on 32-bit systems and to `C:\Program Files (x86)\` on 64-bit systems (the toolset is 32-bit). Alternatively one may compile and install from source as described in our [compiling manual](doc/compiling.md#Windows). @@ -77,8 +74,8 @@ Alternatively one may compile and install from source as described in our [compi We recommend to install from: -* [homebrew](https://formulae.brew.sh/formula/stlink) or -* [MacPorts](https://ports.macports.org/port/stlink) +- [homebrew](https://formulae.brew.sh/formula/stlink) or +- [MacPorts](https://ports.macports.org/port/stlink) Alternatively one can compile and install from source as described in our [compiling manual](doc/compiling.md#macOS). @@ -88,30 +85,28 @@ We recommend to install `stlink-tools` from the package repository of the used d **Note:** As packages distributed via the [Debian](https://packages.debian.org/buster/stlink-tools) and [Ubuntu](https://packages.ubuntu.com/stlink-tools) repositories differ from our self-maintained deb-package, we recommend to use the latter instead (see link below). It provides the opportunity to handle and fix user-reported package issues directly within the project and is not redundant to any limitations deriving from external maintenance guidelines. -* Debian Linux: [(Link)](https://github.com/stlink-org/stlink/releases) -* Ubuntu Linux: [(Link)](https://github.com/stlink-org/stlink/releases) -* Arch Linux: [(Link)](https://www.archlinux.org/packages/community/x86_64/stlink) -* Alpine Linux: [(Link)](https://pkgs.alpinelinux.org/packages?name=stlink) -* Fedora: [(Link)](https://src.fedoraproject.org/rpms/stlink) -* Gentoo Linux: [(Link)](https://packages.gentoo.org/packages/dev-embedded/stlink) +- Debian Linux: [(Link)](https://github.com/stlink-org/stlink/releases) +- Ubuntu Linux: [(Link)](https://github.com/stlink-org/stlink/releases) +- Arch Linux: [(Link)](https://www.archlinux.org/packages/community/x86_64/stlink) +- Alpine Linux: [(Link)](https://pkgs.alpinelinux.org/packages?name=stlink) +- Fedora: [(Link)](https://src.fedoraproject.org/rpms/stlink) +- Gentoo Linux: [(Link)](https://packages.gentoo.org/packages/dev-embedded/stlink) **Other Operating Systems**: -* RedHat/CentOS 8: Users can install from [EPEL repository](https://src.fedoraproject.org/rpms/stlink/branch/epel8) -* FreeBSD: Users can install from [freshports](https://www.freshports.org/devel/stlink) - +- RedHat/CentOS 8: Users can install from [EPEL repository](https://src.fedoraproject.org/rpms/stlink/branch/epel8) +- FreeBSD: Users can install from [freshports](https://www.freshports.org/devel/stlink) ## Installation from source (advanced users) When there is no executable available for your platform or you need the latest (possible unstable) version you need to compile the toolset yourself. This procedure is explained in the [compiling manual](doc/compiling.md). - ## Contributing and versioning -* The semantic versioning scheme is used. Read more at [semver.org](http://semver.org) -* Before creating a pull request, please _ALWAYS_ open a new issue for the discussion of the intended new features. Bugfixes don't require a discussion via a ticket-issue. However they should always be described in a few words as soon as they appear to help others as well. -* Contributors and/or maintainers may submit comments or request changes to patch-proposals and/or pull-requests. -* **ATTENTION: _NEVER EVER_ use the '#' character to count-up single points within a listing as '#' is _exclusively_ reserved for referencing GitHub issues and pull-requests. Otherwise you accidentally introduce false cross references within the project.** -* Please start new forks from the develop branch, as pull requests will go into this branch as well. +- The semantic versioning scheme is used. Read more at [semver.org](http://semver.org) +- Before creating a pull request, please _ALWAYS_ open a new issue for the discussion of the intended new features. Bugfixes don't require a discussion via a ticket-issue. However they should always be described in a few words as soon as they appear to help others as well. +- Contributors and/or maintainers may submit comments or request changes to patch-proposals and/or pull-requests. +- **ATTENTION: _NEVER EVER_ use the '#' character to count-up single points within a listing as '#' is _exclusively_ reserved for referencing GitHub issues and pull-requests. Otherwise you accidentally introduce false cross references within the project.** +- Please start new forks from the develop branch, as pull requests will go into this branch as well. Please also refer to our [Contribution Guidelines](CONTRIBUTING.md). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..caa2740db --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,20 @@ +# Security Policy + +## Supported Versions + +The following versions of the stlink toolset are currently being supported.
As this is a development toolset, please note that bugfixes will only be applied to the latest version. + +| Version | Supported | +| ------- | ------------------ | +| develop | :white_check_mark: | +| 1.6.x | :white_check_mark: | +| 1.5.x | :x: | +| 1.4.0 | :x: | +| 1.3.x | :x: | +| 1.2.0 | :x: | +| 1.1.0 | :x: | +| 1.0.0 | :x: | + +## Reporting a Vulnerability + +Detected vulnerabilities in the toolset should be reported by opening a regular bugreport issue. diff --git a/cmake/modules/Findlibusb.cmake b/cmake/modules/Findlibusb.cmake index bc613779d..257c682ce 100644 --- a/cmake/modules/Findlibusb.cmake +++ b/cmake/modules/Findlibusb.cmake @@ -10,7 +10,7 @@ include(FindPackageHandleStandardArgs) -if (APPLE) # macOS +if (APPLE) # macOS FIND_PATH( LIBUSB_INCLUDE_DIR NAMES libusb.h HINTS /usr /usr/local /opt @@ -27,7 +27,7 @@ if (APPLE) message(FATAL_ERROR "No libusb library found on your system! Install libusb-1.0 from Homebrew or MacPorts") endif () -elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") # FreeBSD; libusb is integrated into the system +elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") # FreeBSD; libusb is integrated into the system FIND_PATH( LIBUSB_INCLUDE_DIR NAMES libusb.h HINTS /usr/include @@ -43,11 +43,13 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") message(FATAL_ERROR "Expected libusb library not found on your system! Verify your system integrity.") endif () -elseif (WIN32 OR (EXISTS "/etc/debian_version" AND MINGW)) # Windows or MinGW-toolchain on Debian - # for MinGW/MSYS/MSVC: 64-bit or 32-bit? +elseif (WIN32 OR (EXISTS "/etc/debian_version" AND MINGW)) # Windows or MinGW-toolchain on Debian + # MinGW/MSYS/MSVC: 64-bit or 32-bit? if (CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "=== Building for Windows (x86-64) ===") set(ARCH 64) else () + message(STATUS "=== Building for Windows (i686) ===") set(ARCH 32) endif () @@ -75,14 +77,14 @@ elseif (WIN32 OR (EXISTS "/etc/debian_version" AND MINGW)) if (NOT LIBUSB_FOUND) # Preparations for installing libusb library - set(LIBUSB_WIN_VERSION 1.0.23) # set libusb version + set(LIBUSB_WIN_VERSION 1.0.23) # set libusb version set(LIBUSB_WIN_ARCHIVE libusb-${LIBUSB_WIN_VERSION}.7z) if (WIN32 AND NOT EXISTS "/etc/debian_version") # ... on native Windows systems set(LIBUSB_WIN_ARCHIVE_PATH ${CMAKE_BINARY_DIR}/${LIBUSB_WIN_ARCHIVE}) set(LIBUSB_WIN_OUTPUT_FOLDER ${CMAKE_BINARY_DIR}/3rdparty/libusb-${LIBUSB_WIN_VERSION}) - else (EXISTS "/etc/debian_version" AND MINGW) # ... only for cross-building on Debian - set(LIBUSB_WIN_ARCHIVE_PATH ${CMAKE_SOURCE_DIR}/build-mingw/${LIBUSB_WIN_ARCHIVE}) - set(LIBUSB_WIN_OUTPUT_FOLDER ${CMAKE_SOURCE_DIR}/build-mingw/3rdparty/libusb-${LIBUSB_WIN_VERSION}) + else (EXISTS "/etc/debian_version" AND MINGW) # ... only for cross-building on Debian + set(LIBUSB_WIN_ARCHIVE_PATH ${CMAKE_SOURCE_DIR}/build-mingw-${ARCH}/${LIBUSB_WIN_ARCHIVE}) + set(LIBUSB_WIN_OUTPUT_FOLDER ${CMAKE_SOURCE_DIR}/build-mingw-${ARCH}/3rdparty/libusb-${LIBUSB_WIN_VERSION}) endif () # Get libusb package diff --git a/cmake/modules/c_flags.cmake b/cmake/modules/c_flags.cmake index 8291ea0ee..5ed0c4d7d 100644 --- a/cmake/modules/c_flags.cmake +++ b/cmake/modules/c_flags.cmake @@ -41,7 +41,7 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") add_cflag_if_supported("-Wredundant-decls") endif () -if (NOT WIN32) +if (NOT (WIN32 OR (EXISTS "/etc/debian_version" AND MINGW))) add_cflag_if_supported("-fPIC") endif () diff --git a/cmake/packaging/windows/generate_binaries.sh b/cmake/packaging/windows/generate_binaries.sh index d38f8d62f..f3642c316 100644 --- a/cmake/packaging/windows/generate_binaries.sh +++ b/cmake/packaging/windows/generate_binaries.sh @@ -6,23 +6,25 @@ #sudo apt-get install mingw-w64 # x86_64 -mkdir build-mingw -cd build-mingw +mkdir build-mingw-64 +cd build-mingw-64 cmake -DCMAKE_SYSTEM_NAME=Windows \ -DTOOLCHAIN_PREFIX=x86_64-w64-mingw32 \ - -DCMAKE_TOOLCHAIN_FILE=./cmake/modules/set_toolchain.cmake .. + -DCMAKE_TOOLCHAIN_FILE=./../cmake/modules/set_toolchain.cmake .. make package -cp dist/*.zip ../build/Release/dist +sudo cp dist/*.zip ../build/Release/dist +make clean cd .. -rm -rf build-mingw +rm -rf build-mingw-64 # i686 -mkdir build-mingw -cd build-mingw +mkdir build-mingw-32 +cd build-mingw-32 cmake -DCMAKE_SYSTEM_NAME=Windows \ -DTOOLCHAIN_PREFIX=i686-w64-mingw32 \ - -DCMAKE_TOOLCHAIN_FILE=./cmake/modules/set_toolchain.cmake .. + -DCMAKE_TOOLCHAIN_FILE=./../cmake/modules/set_toolchain.cmake .. make package -cp dist/*.zip ../build/Release/dist +sudo cp dist/*.zip ../build/Release/dist +make clean cd .. -rm -rf build-mingw +rm -rf build-mingw-32 diff --git a/contributors.txt b/contributors.txt index 38cc9cd42..88f1f0c89 100644 --- a/contributors.txt +++ b/contributors.txt @@ -113,6 +113,7 @@ Simon Wright Stany Marcel Stefan Misik Sven Wegener +Tarek Bochkati [tarek-bochkati] (STMicroelectronics) Timothy Lee [timothytylee] Tuomo Kaikkonen Theodore A. Roth diff --git a/doc/compiling.md b/doc/compiling.md index 07193f357..eef207f95 100644 --- a/doc/compiling.md +++ b/doc/compiling.md @@ -1,14 +1,14 @@ # Compiling from sources ## Microsoft Windows (10, 8.1) + ### Common Requirements On Windows users should ensure that the following software is installed: -* `git` (_optional, but recommended_) -* `cmake` (3.17.0 or later) -* `MinGW-w64` (7.0.0 or later) with GCC toolchain 8.1.0 - +- `git` (_optional, but recommended_) +- `cmake` (3.17.0 or later) +- `MinGW-w64` (7.0.0 or later) with GCC toolchain 8.1.0 ### Installation @@ -16,12 +16,14 @@ On Windows users should ensure that the following software is installed: 2. Install `cmake` from
Ensure that you add cmake to the $PATH system variable when following the instructions by the setup assistant. 3. Install - - _EITHER_: **MinGW-w64** from (mingw-w64-install.exe)
- - _OR_: **MSVC toolchain** from Visual Studio Build Tools 2019 + +- _EITHER_: **MinGW-w64** from (mingw-w64-install.exe)
+- _OR_: **MSVC toolchain** from Visual Studio Build Tools 2019 + 4. Create a new destination folder at a place of your choice 5. Open the command-line (cmd.exe) and execute `cd C:\$Path-to-your-destination-folder$\` 6. Fetch the project sourcefiles by running `git clone https://github.com/stlink-org/stlink.git`from the command-line (cmd.exe)
- or download the stlink zip-sourcefolder from the Release page on GitHub + or download the stlink zip-sourcefolder from the Release page on GitHub #### MSVC toolchain - minimal installation @@ -31,15 +33,19 @@ Visual Studio IDE is not necessary, only Windows SDK & build tools are required 2. Navigate through menus as follows (might change overtime) `All downloads > Tools for Visual Studio 2019 > Build Tools for Visual Studio 2019 > Download` + 3. Start downloaded executable. After Visual Studio Installer bootstraps and main window pops up, open `Individual Components` tab, and pick - - latest build tools (eg. `MSVC v142 - VS 2019 C++ x64/x86 build tools (v14.25)`) - - latest Windows SDK (eg. `Windows 10 SDK (10.0.18362.0)`) + +- latest build tools (eg. `MSVC v142 - VS 2019 C++ x64/x86 build tools (v14.25)`) +- latest Windows SDK (eg. `Windows 10 SDK (10.0.18362.0)`) + 4. After installation finishes, you can press `Launch` button in Visual Studio Installer's main menu. - Thus you can open `Developer Command Prompt for VS 2019`. It is `cmd.exe` instance with adjusted PATHs including eg. `msbuild`. - Alternatively, you can use `Developer Powershell for VS 2019` which is the same thing for `powershell.exe`. Both are available from Start menu. - Another option is to add `msbuild` to PATH manually. Its location should be `C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin`. Then, it should be available from any `powershell.exe` or `cmd.exe` session. ### Building + #### MinGW-w64 1. Use the command-line to move to the `scripts` directory within the source-folder: `cd stlink\scripts\` @@ -50,7 +56,6 @@ Per default the build script (currently) uses `C:\Program Files\mingw-w64\x86_64 When installing different toolchains make sure to update the path in the `mingw64-build.bat`.
This can be achieved by opening the .bat file with a common text editor. - #### MSVC toolchain 1. In a command prompt, change the directory to the folder where the stlink files were cloned (or unzipped) to. @@ -59,12 +64,15 @@ This can be achieved by opening the .bat file with a common text editor. This will create a solution file `stlink.sln` in the build folder. Now, you can build whole `stlink` suite using following command: + ``` msbuild /m /p:Configuration=Release stlink.sln ``` + Options: + - `/m` - compilation runs in parallel utilizing multiple cores -- `/p:Configuration=Release` - generates *Release*, optimized build. +- `/p:Configuration=Release` - generates _Release_, optimized build. Directory `\build\Release` contains final executables. (`st-util.exe` is located in `\build\src\gdbserver\Release`). @@ -79,25 +87,25 @@ It can be copied from: `\build\3rdparty\libusb-{version}\MS{arch}\ [ST-LINK drivers](https://www.st.com/en/development-tools/stsw-link009.html) are required for `stlink` to work. ## Linux + ### Common requirements Install the following packages from your package repository: -* `git` -* `gcc` or `clang` or `mingw32-gcc` or `mingw64-gcc` (C-compiler; very likely gcc is already present) -* `build-essential` (on Debian based distros (Debian, Ubuntu)) -* `cmake` (3.4.2 or later, use the latest version available from the repository) -* `rpm` (on Debian based distros (Debian, Ubuntu), needed for package build with `make package`) -* `libusb-1.0` -* `libusb-1.0-0-dev` (development headers for building) -* `libgtk-3-dev` (_optional_, needed for `stlink-gui`) -* `pandoc` (_optional_, needed for generating manpages from markdown) +- `git` +- `gcc` or `clang` or `mingw32-gcc` or `mingw64-gcc` (C-compiler; very likely gcc is already present) +- `build-essential` (on Debian based distros (Debian, Ubuntu)) +- `cmake` (3.4.2 or later, use the latest version available from the repository) +- `rpm` (on Debian based distros (Debian, Ubuntu), needed for package build with `make package`) +- `libusb-1.0` +- `libusb-1.0-0-dev` (development headers for building) +- `libgtk-3-dev` (_optional_, needed for `stlink-gui`) +- `pandoc` (_optional_, needed for generating manpages from markdown) or execute (Debian-based systems only): `apt-get install gcc build-essential cmake libusb-1.0 libusb-1.0-0-dev libgtk-3-dev pandoc` (Replace gcc with the intended C-compiler if necessary or leave out any optional package not needed.) - ### Installation 1. Open a new terminal console @@ -105,7 +113,6 @@ or execute (Debian-based systems only): `apt-get install gcc build-essential cma 3. Change to this directory: `cd ~/git` 4. Fetch the project sourcefiles by running `git clone https://github.com/stlink-org/stlink.git` - ### Building #### Installation: @@ -120,21 +127,19 @@ or execute (Debian-based systems only): `apt-get install gcc build-essential cma As an option you may also install to an individual user-defined folder e.g `$HOME` with `make install DESTDIR=$HOME`. - -#### Removal: +#### Removal: 1. Run `make uninstall` to perform a clean uninstall of the package from the system. 2. Run `make clean` to clean the build-folder within the project source and remove all compiled and linked files and libraries. - ### Cross-Building for Windows Install the following packages from your package repository: -* `mingw-w64` -* `mingw-w64-common` -* `mingw-w64-i686-dev` -* `mingw-w64-x86-64-dev` +- `mingw-w64` +- `mingw-w64-common` +- `mingw-w64-i686-dev` +- `mingw-w64-x86-64-dev` After following the steps for installation above, proceed with from the build dircetory itself: @@ -144,7 +149,6 @@ $ sudo sh ./cmake/packaging/windows/generate_binaries.sh The generated zip-packages can be found in the subdirectory `./build/dist`. - ### Set device access permissions and the role of udev By default most distributions don't allow access to USB devices. @@ -162,22 +166,21 @@ $ sudo udevadm trigger udev will now create device node files, e.g. `/dev/stlinkv3_XX`, `/dev/stlinkv2_XX`, `/dev/stlinkv1_XX`. - ### Special note on the use of STLink/V1 programmers (legacy): As the STLINKV1's SCSI emulation is somehow broken, the best advice possibly is to tell your operating system to completely ignore it.
Choose one of the following options _before_ connecting the device to your computer: -* `modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i` -* _OR_ - 1. `echo "options usb-storage quirks=483:3744:i" >> /etc/modprobe.conf` - 2. `modprobe -r usb-storage && modprobe usb-storage` -* _OR_ - 1. `cp stlink_v1.modprobe.conf /etc/modprobe.d` - 2. `modprobe -r usb-storage && modprobe usb-storage` - +- `modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i` +- _OR_ + 1. `echo "options usb-storage quirks=483:3744:i" >> /etc/modprobe.conf` + 2. `modprobe -r usb-storage && modprobe usb-storage` +- _OR_ + 1. `cp stlink_v1.modprobe.conf /etc/modprobe.d` + 2. `modprobe -r usb-storage && modprobe usb-storage` ## macOS + ### Common requirements The best and recommended way is to install a package manager for open source software, @@ -185,21 +188,20 @@ either [homebrew](https://brew.sh) or [MacPorts](https://www.macports.org/). Then install the following dependencies from the package repository: -* `git` -* `gcc` or `llvm` (for clang) (C-compiler) -* `cmake` -* `libusb` -* `gtk+3` or `gtk3` (_optional_, needed for `stlink-gui`) +- `git` +- `gcc` or `llvm` (for clang) (C-compiler) +- `cmake` +- `libusb` +- `gtk+3` or `gtk3` (_optional_, needed for `stlink-gui`) To do this with only one simple command, type: -* for homebrew: - - with gcc: `sudo brew install git gcc cmake libusb gtk+3` or - - with clang: `sudo brew install git llvm cmake libusb gtk+3` or -* for MacPorts: - - with gcc: `sudo port install git gcc10 cmake libusb gtk3` or - - with clang: `sudo port install git llvm-10 cmake libusb gtk3` - +- for homebrew: + - with gcc: `sudo brew install git gcc cmake libusb gtk+3` or + - with clang: `sudo brew install git llvm cmake libusb gtk+3` or +- for MacPorts: + - with gcc: `sudo port install git gcc10 cmake libusb gtk3` or + - with clang: `sudo port install git llvm-10 cmake libusb gtk3` ### Installation @@ -208,7 +210,6 @@ To do this with only one simple command, type: 3. Change to this directory: `cd ~/git` 4. Fetch the project sourcefiles by running `git clone https://github.com/stlink-org/stlink.git` - ### Building 1. Change into the project source directory: `cd stlink` @@ -217,14 +218,13 @@ To do this with only one simple command, type: 4. Run `make debug` to create the _Debug_ target (_optional_)
The debug target is only necessary in order to modify the sources and to run under a debugger. - ## Build options + ### Build using a different directory for shared libs To put the compiled shared libs into a different directory during installation, you can use the cmake option `cmake -DLIB_INSTALL_DIR:PATH="/usr/lib64" ..`. - ### Standard installation directories The cmake build system of this toolset includes `GNUInstallDirs` to define GNU standard installation directories. @@ -232,8 +232,7 @@ This module provides install directory variables as defined by the GNU Coding St Below are the preset default cmake options, which apply if none of these options are redefined: -* `-DCMAKE_INSTALL_SYSCONFDIR=/etc` -* `-DCMAKE_INSTALL_PREFIX=/usr/local` - +- `-DCMAKE_INSTALL_SYSCONFDIR=/etc` +- `-DCMAKE_INSTALL_PREFIX=/usr/local` Author: nightwalker-87 diff --git a/doc/dev/developer.txt b/doc/dev/developer.txt index 9c4da22f7..e3091c003 100644 --- a/doc/dev/developer.txt +++ b/doc/dev/developer.txt @@ -244,18 +244,19 @@ Description: Backend: "jtag_reset" Arguments: sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb() - value: 0: drive low, 1: drive high, 2: ???? + value: 0: drive low, 1: drive high, 2: pulse Return: -1 for error. 0 for success. Include: inc/stlink.h -Prototype: int stlink_run(stlink_t *sl); +Prototype: int stlink_run(stlink_t *sl, enum run_type type); Definition: src/common.c Description: Just calls the backend "run" procedure. Backend: "run" Arguments: - sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb() + sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb() + type: RUN_NORMAL - run target, RUN_FLASH_LOADER - run target with masking interrupts Return: -1 for error. 0 for success. Include: inc/stlink.h diff --git a/doc/devices_boards.md b/doc/devices_boards.md index 97094b972..df4b5ed29 100644 --- a/doc/devices_boards.md +++ b/doc/devices_boards.md @@ -1,15 +1,13 @@ -Boards supported by the STlink toolset -====================================== +# Boards supported by the STlink toolset -The following devices are supported by the STlink tools. - -All Boards are expected to work with ST-Link-v2 programmers. +The following devices are supported by the stlink toolset. +All Boards are expected to work with ST-LINK/V2 programmers. **STM32F0 / ARM Cortex M0 / Core-ID: 0x0bb11477 (STM32F0_CORE_ID)** | Chip-ID | Product-Code | -| --- | --- | +| ------- | ------------------- | | 0x440 | STM32F0**30**x**8** | | 0x442 | STM32F0**30**x**C** | | 0x444 | STM32F0**3**xx**4** | @@ -22,19 +20,19 @@ All Boards are expected to work with ST-Link-v2 programmers. | 0x448 | STM32F0**72**xx | | 0x442 | STM32F0**9**xxx | -Tested boards [incl. STLink programmers]: -* Nucleo-F030R8 [v2-1] -* Nucleo-32 [v2-1] -* STM32F0-Discovery [v2] -* STM320518-EVAL -* Nucleo-F072RB [v2-1] -* Nucleo-F091RC [v2-1] +Tested boards [incl. STLINK programmers]: +- Nucleo-F030R8 [v2-1] +- Nucleo-F072RB [v2-1] +- Nucleo-F091RC [v2-1] +- Nucleo-32 [v2-1] +- STM32F0-Discovery [v2] +- STM320518-EVAL **STM32F1 / ARM Cortex M3 / Core-ID: 0x1ba01477 (STM32F1_CORE_ID)** | Product-Code | Product Line | -| --- | --- | +| ----------------- | ----------------------- | | STM32F10**0**yyxx | Value line (V) | | STM32F10**1**yyxx | Access line (A) | | STM32F10**2**yyxx | USB Access line (USB-A) | @@ -42,86 +40,83 @@ Tested boards [incl. STLink programmers]: | STM32F10**5**yyxx | Connectivity line (C) | | STM32F10**7**yyxx | Connectivity line (C) | -| Chip-ID | Product Line | Code (yy) | V | A | USB-A | P | C | -| --- | --- | --- | --- | --- | --- | --- | --- | -| 0x412 | Low-Density | x4 x6 | F100 | F101 | F102 | F103 | | -| 0x410 | Medium Density | x8 xB | | F101 | F102 | F103 | | -| 0x414 | High density | xC xD xE | | F101 | F103 | | | +| Chip-ID | Product Line | Code (yy) | V | A | USB-A | P | C | +| ------- | -------------------- | --------- | ---- | ---- | ----- | ---- | -------------- | +| 0x412 | Low-Density | x4 x6 | F100 | F101 | F102 | F103 | | +| 0x410 | Medium Density | x8 xB | | F101 | F102 | F103 | | +| 0x414 | High density | xC xD xE | | F101 | F103 | | | | 0x418 | STM32F105xx/107xx | x8 xB xC | | | | | F105
F107 | -| 0x420 | Medium density value | x8 xB | F100 | | | | | -| 0x428 | High density Value | xC xD xE | F100 | | | | | -| 0x430 | XL-Density | xF xG | | F101 | | F103 | | +| 0x420 | Medium density value | x8 xB | F100 | | | | | +| 0x428 | High density Value | xC xD xE | F100 | | | | | +| 0x430 | XL-Density | xF xG | | F101 | | F103 | | -Tested boards [incl. STLink programmers]: -* STM32VL-Discovery (STM32F100RBT6) with STLink-v1 [v1], [v2] -* STM32F103-Bluepill: C8Tx & R8xx [v2] -* Nucleo-F103RB [v2-1] -* HY-STM32 (STM32F103VETx) [v1, v2] -* DecaWave EVB1000 (STM32F105RCTx) [v1, v2] +Tested boards [incl. STLINK programmers]: +- STM32VL-Discovery (STM32F100RBT6) with STLINK/V1 [v1], [v2] +- STM32F103-Bluepill: C8Tx & R8xx [v2] +- Nucleo-F103RB [v2-1] +- HY-STM32 (STM32F103VETx) [v1, v2] +- DecaWave EVB1000 (STM32F105RCTx) [v1, v2] **STM32F2 / ARM Cortex M3 / Core-ID: 0x2ba01477 (STM32F2_CORE_ID)** -| Chip-ID | Product-Code | Product Line | -| --- | --- | --- | -| 0x411 | STM32F2yyxx | (all devices) | - +| Chip-ID | Product-Code | Product Line | +| ------- | ------------ | ------------- | +| 0x411 | STM32F2yyxx | (all devices) | **STM32F1 / ARM Cortex M3 / Core-ID: 0x2ba01477 (STM3F1c_CORE_ID)** -| Product-Code | Chip-ID | STLink
Programmer | Boards | -| --- | --- | --- | --- | -| CKS32F103C8Tx | 0x410 | v2 | "STM32"-Bluepill ( _**Fake-Marking !**_ )
STM32F103C8T6 clone from China Key Systems (CKS) | -| CKS32F103C8Tx | 0x410 | v2 | CKS32-Bluepill (Clone)
STM32F103C8T6 clone from China Key Systems (CKS) | - +| Product-Code | Chip-ID | STLink
Programmer | Boards | +| ------------- | ------- | ---------------------- | ----------------------------------------------------------------------------------------------- | +| CKS32F103C8Tx | 0x410 | v2 | "STM32"-Bluepill ( _**Fake-Marking !**_ )
STM32F103C8T6 clone from China Key Systems (CKS) | +| CKS32F103C8Tx | 0x410 | v2 | CKS32-Bluepill (Clone)
STM32F103C8T6 clone from China Key Systems (CKS) | **STM32F3 / ARM Cortex M4F / Core-ID: 0x2ba01477 (STM32F3_CORE_ID)** -| Product-Code | Product Line | -| --- | --- | -| STM32F3**01**yyxx | Access line (A) | -| STM32F3**02**yyxx | USB & CAN line (USB/CAN) | -| STM32F3**03**yyxx | Performance line (P) | -| STM32F3**34**yy | Digital Power line (DP) | -| STM32F3**73**yy | Precision Measurement line (PM) 64k/16k / 128k/24k / 265k/32k | -| STM32F3**18**yy | General Purpose line (GP) 64k/16k | -| STM32F3**28**yy | General Purpose line (GP) 64k/16k | -| STM32F3**58**yy | General Purpose line (GP) 265k/48k | -| STM32F3**78**yy | Precision Measurement line (PM) 265k/32k | -| STM32F3**98**yy | General Purpose line (GP) 512k/80k | - -| Chip-ID | Product Line | Code (yy) | A | USB/CAN | P | others | -| --- | --- | --- | --- | --- | --- | --- | -| 0x422 | _N/A_ | xB xC | | F302 | F303 | | -| 0x422 | _N/A_ | - | | | | F358 | +| Product-Code | Product Line | +| ----------------- | ------------------------------------------------------------- | +| STM32F3**01**yyxx | Access line (A) | +| STM32F3**02**yyxx | USB & CAN line (USB/CAN) | +| STM32F3**03**yyxx | Performance line (P) | +| STM32F3**34**yy | Digital Power line (DP) | +| STM32F3**73**yy | Precision Measurement line (PM) 64k/16k / 128k/24k / 265k/32k | +| STM32F3**18**yy | General Purpose line (GP) 64k/16k | +| STM32F3**28**yy | General Purpose line (GP) 64k/16k | +| STM32F3**58**yy | General Purpose line (GP) 265k/48k | +| STM32F3**78**yy | Precision Measurement line (PM) 265k/32k | +| STM32F3**98**yy | General Purpose line (GP) 512k/80k | + +| Chip-ID | Product Line | Code (yy) | A | USB/CAN | P | others | +| ------- | ------------ | --------- | ---- | ------- | ---- | -------------- | +| 0x422 | _N/A_ | xB xC | | F302 | F303 | | +| 0x422 | _N/A_ | - | | | | F358 | | 0x432 | _N/A_ | - | | | | F373
F378 | -| 0x438 | _N/A_ | x4 x6 x8 | | | F303 | | +| 0x438 | _N/A_ | x4 x6 x8 | | | F303 | | | 0x438 | _N/A_ | - | | | | F334
F328 | -| 0x439 | _N/A_ | x4 x6 x8 | F301 | F302 | | | -| 0x439 | _N/A_ | - | | | | F318 | -| 0x446 | _N/A_ | xD xE | | F302 | F303 | | -| 0x446 | _N/A_ | - | | | | F398 | +| 0x439 | _N/A_ | x4 x6 x8 | F301 | F302 | | | +| 0x439 | _N/A_ | - | | | | F318 | +| 0x446 | _N/A_ | xD xE | | F302 | F303 | | +| 0x446 | _N/A_ | - | | | | F398 | -Tested boards [incl. STLink programmers]: -* Nucleo-F302K8 [v2-1] -* Nucleo-F303K8 [v2-1] -* STM32F3348-Discovery [v2-1] -* Nucleo-F334R8 [v2-1] -* STM32F303-Discovery [v2] -* Nucleo-F303RE [v2-1] +Tested boards [incl. STLINK programmers]: +- Nucleo-F302K8 [v2-1] +- Nucleo-F303K8 [v2-1] +- Nucleo-F303RE [v2-1] +- Nucleo-F334R8 [v2-1] +- STM32F303-Discovery [v2] +- STM32F3348-Discovery [v2-1] **STM32F3 / ARM Cortex M4F / Core-ID: 0x2ba01477 (STM32F3c_CORE_ID)** -| Product-Code | Chip-ID | STLink
Programmer | Boards | -| --- | --- | --- | --- | -| GD32F303VGT6 | 0x430 | _N/A_ | STM32F303 clone from GigaDevice GD)
_unsupported_ | - +| Product-Code | Chip-ID | STLINK
Programmer | Boards | +| ------------ | ------- | ---------------------- | ---------------------------------- | +| GD32F303VGT6 | 0x430 | [v2] | STM32F303 clone from GigaDevice GD | **STM32F4 / ARM Cortex M4F / Core-ID: 0x2ba01477 (STM32F4_CORE_ID)** | Chip-ID | Product-Code | -| --- | --- | +| ------- | ------------------- | | 0x413 | STM32F4**0**xxx | | 0x413 | STM32F4**1**xxx | | 0x419 | STM32F4**2**xxx | @@ -139,20 +134,20 @@ Tested boards [incl. STLink programmers]: | 0x463 | STM32F4**13**xx | | 0x463 | STM32F4**23**xx | -Tested boards [incl. STLink programmers]: -* STM32F407-Discovery [v2] -* 32F411E-Discovery with gyro, audio [v2] -* 32F429I-Discovery with LCD [v2] -* 32F439VIT6-Discovery [v2] (reseated MCU) -* Nucleo-F401RE [v2-1] -* Nucleo-F411RE [v2-1] -* 32F413H-Discovery [v2-1] +Tested boards [incl. STLINK programmers]: +- Nucleo-F401RE [v2-1] +- Nucleo-F411RE [v2-1] +- STM32F407-Discovery [v2] +- STM32F411E-Discovery with gyro, audio [v2] +- STM32F413H-Discovery [v2-1] +- STM32F429I-Discovery with LCD [v2] +- STM32F439VIT6-Discovery [v2] (reseated MCU) **STM32F7 / ARM Cortex M7F / Core-ID: 0x5ba02477 (STM32F7_CORE_ID)** | Chip-ID | Product-Code | -| --- | --- | +| ------- | --------------- | | 0x452 | STM32F7**2**xxx | | 0x452 | STM32F7**3**xxx | | 0x449 | STM32F7**4**xxx | @@ -160,37 +155,45 @@ Tested boards [incl. STLink programmers]: | 0x451 | STM32F7**6**xxx | | 0x451 | STM32F7**7**xxx | -Tested boards [incl. STLink programmers]: -* STM32F756NGHx evaluation board [v2-1] -* 32F769I-Discovery [v2-1] -* Nucleo-F722ZE [v2-1] -* Nucleo-F746ZG [v2-1] +Tested boards [incl. STLINK programmers]: + +- Nucleo-F722ZE [v2-1] +- Nucleo-F746ZG [v2-1] +- STM32F756NGHx evaluation board [v2-1] +- STM32F769I-Discovery [v2-1] + +**STM32H7 / ARM Cortex M7F / Core-ID: 0x6ba02477 (STM32H7_CORE_ID)** + +| Chip-ID | Product-Code | +| ------- | -------------- | +| 0x450 | STM32H74x/H75x | + +Tested boards [incl. STLINK programmers]: +- Nucleo-H745I-Q [v3] **STM32G0 / ARM Cortex M0+ / Core-ID: 0x0bc11477 (STM32G0_CORE_ID)** | Chip-ID | Product-Code | -| --- | --- | +| ------- | --------------- | | 0x466 | STM32G0**3**xxx | | 0x466 | STM32G0**4**xxx | | 0x460 | STM32G0**7**xxx | | 0x460 | STM32G0**8**xxx | - **STM32G4 / ARM Cortex M4F / Core-ID: 0x2ba01477 (STM32G4_CORE_ID)** | Chip-ID | Product-Code | -| --- | --- | +| ------- | --------------- | | 0x468 | STM32G4**31**xx | | 0x468 | STM32G4**41**xx | | 0x469 | STM32G4**7**xxx | | 0x469 | STM32G4**8**xxx | - **STM32L0 / ARM Cortex M0+ / Core-ID: 0x0bc11477 (STM32L0_CORE_ID)** | Chip-ID | Product-Code | -| --- | --- | +| ------- | --------------- | | 0x457 | STM32L0**1**xxx | | 0x457 | STM32L0**2**xxx | | 0x425 | STM32L0**31**xx | @@ -200,14 +203,14 @@ Tested boards [incl. STLink programmers]: | 0x447 | STM32L0**7**xxx | | 0x447 | STM32L0**8**xxx | -Tested boards [incl. STLink programmers]: -* Nucleo-L053R8 [v2-1] +Tested boards [incl. STLINK programmers]: +- Nucleo-L053R8 [v2-1] **STM32L1 / ARM Cortex M3 / Core-ID: 0x2ba01477 (STM32L1_CORE_ID)** | Chip-ID | Product-Code | -| --- | --- | +| ------- | ---------------- | | 0x416 | STM32L1xxx**6** | | 0x416 | STM32L1xxx**8** | | 0x416 | STM32L1xxx**B** | @@ -218,42 +221,42 @@ Tested boards [incl. STLink programmers]: | 0x436 | STM32L1xxx**D** | | 0x437 | STM32L1xxx**E** | -Tested boards [incl. STLink programmers]: -* Nucleo-L152RE [v2-1] -* 32L152C-Discovery [v2] +Tested boards [incl. STLINK programmers]: +- Nucleo-L152RE [v2-1] +- STM32L152C-Discovery [v2] **STM32L4 / ARM Cortex M4F / Core-ID: 0x2ba01477 (STM32L4_CORE_ID)** -| Chip-ID | Product-Code | -| --- | --- | -| 0x464 | STM32L4**12**xx | -| 0x464 | STM32L4**22**xx | -| 0x435 | STM32L4**3**xxx | -| 0x435 | STM32L4**4**xxx | -| 0x462 | STM32L4**5**xxx | -| 0x462 | STM32L4**6**xxx | -| 0x415 | STM32L4**7**xxx | -| 0x415 | STM32L4**8**xxx | -| 0x461 | STM32L4**96**xx | -| 0x461 | STM32L4**A6**xx | -| 0x470 | STM32L4**R**xx | -| 0x470 | STM32L4**S**xx | -| 0x471 | STM32L4**P5**xx | -| 0x471 | STM32L4**Q5**xx | - -Tested boards [incl. STLink programmers]: -* Nucleo-L432KC [v2-1] -* Nucleo-L452RE [v2-1] -* Nucleo-L476RG [v2-1] -* Nucleo-L496ZG [v2-1] -* 32L4R9I-Discovery [v2-1] - +| Chip-ID | Product-Code | +| ------- | --------------- | +| 0x464 | STM32L4**12**xx | +| 0x464 | STM32L4**22**xx | +| 0x435 | STM32L4**3**xxx | +| 0x435 | STM32L4**4**xxx | +| 0x462 | STM32L4**5**xxx | +| 0x462 | STM32L4**6**xxx | +| 0x415 | STM32L4**7**xxx | +| 0x415 | STM32L4**8**xxx | +| 0x461 | STM32L4**96**xx | +| 0x461 | STM32L4**A6**xx | +| 0x470 | STM32L4**R**xx | +| 0x470 | STM32L4**S**xx | +| 0x471 | STM32L4**P5**xx | +| 0x471 | STM32L4**Q5**xx | + +Tested boards [incl. STLINK programmers]: + +- Nucleo-L432KC [v2-1] +- Nucleo-L452RE [v2-1] +- Nucleo-L476RG [v2-1] +- Nucleo-L496ZG [v2-1] +- STM32L4R9I-Discovery [v2-1] **STM32W / ARM Cortex M3 / Core-ID: 0x2ba01477 (STM32W_CORE_ID)** -| Chip-ID | Product-Code | -| --- | --- | -| 0x495 | STM32WB**50**xx | -| 0x495 | STM32WB**55**xx | -| 0x497 | STM32WLE**5**xx | +| Chip-ID | Product-Code | +| ------- | --------------- | +| 0x495 | STM32WB**50**xx | +| 0x495 | STM32WB**55**xx | +| 0x497 | STM32WLE**5**xx | diff --git a/doc/man/st-flash.1 b/doc/man/st-flash.1 index c2654f280..086046d2c 100644 --- a/doc/man/st-flash.1 +++ b/doc/man/st-flash.1 @@ -41,7 +41,7 @@ Print version information TODO .TP --reset -TODO +Trigger a reset both before and after flashing .TP --opt Enable ignore ending empty bytes optimization diff --git a/doc/man/st-flash.md b/doc/man/st-flash.md index d5565e923..80130c8f1 100644 --- a/doc/man/st-flash.md +++ b/doc/man/st-flash.md @@ -46,7 +46,7 @@ reset : TODO \--reset -: TODO +: Trigger a reset both before and after flashing \--opt : Enable ignore ending empty bytes optimization diff --git a/doc/man/st-info.1 b/doc/man/st-info.1 index a0380f851..776ec7a3f 100644 --- a/doc/man/st-info.1 +++ b/doc/man/st-info.1 @@ -37,9 +37,6 @@ Display the chip ID of the device .B \-\-serial Display the serial code of the device .TP -.B \-\-hla\-serial -Display the hex escaped serial code of the device -.TP .B \-\-probe Display the summarized information of the connected programmers and devices diff --git a/doc/man/st-info.md b/doc/man/st-info.md index 9164642f2..91f9ea0b0 100644 --- a/doc/man/st-info.md +++ b/doc/man/st-info.md @@ -13,7 +13,7 @@ st-info - Provides information about connected STLink and STM32 devices # DESCRIPTION Provides information about connected STLink programmers and STM32 devices: -Serial code, OpenOCD hla-serial, flash, page size, sram, chipid, description. +Serial code, flash, page size, sram, chipid, description. The STLink device to probe can be specified via the environment variable STLINK_DEVICE on the format :. @@ -29,9 +29,6 @@ STLINK_DEVICE on the format :. \--serial : Display the serial code of the device -\--hla-serial -: Display the hex escaped serial code of the device - \--flash : Display amount of flash memory available in the device @@ -53,8 +50,7 @@ Display information about connected programmers and devices $ st-info --probe Found 1 stlink programmers - serial: 303033413030323233343338353130323334333133393339 - hla-serial: "\x30\x30\x33\x41\x30\x30\x32\x32\x33\x34\x33\x38\x35\x31\x30\x32\x33\x34\x33\x31\x33\x39\x33\x39" + serial: 57FF72067265575742132067 flash: 131072 (pagesize: 128) sram: 20480 chipid: 0x0447 diff --git a/doc/tutorial.md b/doc/tutorial.md index f13c4c6f1..71af3d45e 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -2,14 +2,17 @@ ## Available tools and options -| Option | Tool | Description | Available
since | -| --------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | -| --flash=n[k][m] | st-flash | One can specify `--flash=128k` for example, to override the default value of 64k
for the STM32F103C8T6 to assume 128k of flash being present. This option accepts
decimal (128k), octal 0200k, or hex 0x80k values. Leaving the multiplier out is
equally valid, e.g.: `--flash=0x20000`. The size may be followed by an optional "k"
or "m" to multiply the given value by 1k (1024) or 1M respectively. | v1.4.0 | -| --freq=n[k][m] | st-flash,
st-util | The frequency of the SWD/JTAG interface can be specified, to override the default
1800 kHz configuration. This option solely accepts decimal values (5K or 1.8M) with
the unit `Hz` being left out. Valid frequencies are `5K, 15K, 25K, 50K, 100K,`
`125K, 240K, 480K, 950K, 1200K(1.2M), 1800K(1.8M), 4000K(4M)`. | v1.6.1 | -| --opt | st-flash | Optimisation can be enabled in order to skip flashing empty (0x00 or 0xff) bytes at
the end of binary file. This may cause some garbage data left after a flash operation.
This option was enabled by default in earlier releases. | v1.6.1 | -| --reset | st-flash | Trigger a reset both before and after flashing. | v1.0.0 | -| --version | st-info,
st-flash,
st-util | Print version information. | | -| --help | st-flash,
st-util | Print list of available commands. _(To be added to this table.)_ | | +| Option | Tool | Description | Available
since | +| --------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- | +| --flash=n[k][m] | st-flash | One can specify `--flash=128k` for example, to override the default value of 64k for the STM32F103C8T6
to assume 128k of flash being present. This option accepts decimal (128k), octal 0200k, or hex 0x80k values.
Leaving the multiplier out is equally valid, e.g.: `--flash=0x20000`. The size may be followed by an optional
"k" or "m" to multiply the given value by 1k (1024) or 1M respectively. | v1.4.0 | +| --freq=n[k][m] | st-info
st-flash
st-util | The frequency of the SWD/JTAG interface can be specified, to override the default 1800 kHz configuration.
This option solely accepts decimal values (5K or 1.8M) with the unit `Hz` being left out. Valid frequencies are:
`5K, 15K, 25K, 50K, 100K, 125K, 240K, 480K, 950K, 1200K, 1800K, 4000K(4M)`. | v1.6.1 | +| --opt | st-flash | Optimisation can be enabled in order to skip flashing empty (0x00 or 0xff) bytes at the end of binary file.
This may cause some garbage data left after a flash operation. This option was enabled by default in earlier releases. | v1.6.1 | +| --reset | st-flash | Trigger a reset after flashing. The default uses the hardware reset through `NRST` pin.
A software reset (via `AIRCR`; since v1.5.1) is used, if the hardware reset failed (`NRST` pin not connected). | v1.0.0 | +| --connect-under-reset | st-info
st-flash
st-util | Connect under reset. Option makes it possible to connect to the device before code execution. This is useful
when the target contains code that lets the device go to sleep, disables debug pins or other special code. | v1.6.1 | +| --hot-plug | st-info
st-flash
st-util | Connect to the target without reset. | v1.6.2 | +| --probe | st-info | Display hardware information about the connected programmer and target MCU. | v1.2.0 | +| --version | st-info
st-flash
st-util | Print version information. | v1.3.0 | +| --help | st-flash
st-util | Print list of available commands. | | ### st-flash: Checksum for binary files @@ -101,17 +104,54 @@ Check your hardware and try to identify what you have in front of you before ass Please let us know, if you come across any further websites or tutorials that help to identify STM32 fake chips so we can list them here to help others. ---- +### c) Appearance of the warning message `WARN src/common.c: unknown chip id!` + +The chip ID is the main identifier for STM32 MCU and their specific type and provides primary information on flash and SRAM architecture. +This so called `DBGMCU_IDCODE` register is allocated either at memory address `0xE0042000` or `0x40015800`. + +A failure of chip identification results in the error `WARN src/common.c: unknown chip id!`. +There are different variants of this message that refer to different issues: + +- `unknown chip id! 0` --> Target chip (board) is unknown. + 1. Microcontroller is in stop/standby mode. + 2. The signals `DIO` and `CLK` are reversed on the SWD-Interface. +- `unknown chip id! 0x1a` --> _currently unknown_ +- `unknown chip id! 0x001f` --> _currently unknown_ +- `unknown chip id! 0x3e8` --> _currently unknown_ +- `unknown chip id! 0xa05f0000` --> _currently unknown_ +- `unknown chip id! 0x3748` --> A target chip (board) cannot be detected. + 1. No target is connected --> In this case `st-info --probe` displays `chip id 0x0748` with STLINK/V2 and `chip id 0x03e8` with STLINK-V3. + 2. The chip is connected but has gone into an undefined state of operation where the SWD pins are unresponsive. --> Try to use `--connect-under-reset` while pressing the reset button on the target board. + 3. A firmware-issue prevents the programmer from normal operation. --> Ensure that your programmer runs the latest firmware version and consider to upgrade any older version by using the official firmware upgrade tool provided by STMicroelectronics. +- `unknown chip id! 0xe0042000` --> The memory register holding the information on the chip ID could not be read. The following problems may lead to this case: + 1. This problem is caused by the SWDIO and SWCLK being configured for other purpose (GPIO, etc) other than Serial Wire configuration or Jtag --> A possible solution to this is to short the `BOOT0` pin with `VDD` (1) and to reset the chip / board by the execuing `st-flash erase` in order to return the MCU back to normal operation. Afterwards `BOOT0` should be set back to `GND` (0). + 2. There is a hardware defect in the connection between the MCU and the used programmer (solder points, cables, connectors). + +### d) Understanding hardware and software reset functionality for `st-flash` and reset-related device recovery + +Typically a reset signal is sent via the reset pin `NRST`. Using `st-flash` for flashing results in the following behaviour: -( Content below is currently unrevised and may be outdated as of Apr 2020. ) +- without the `--reset` option: `st-flash write` results in one reset signal on the `NRST` line +- with the `--reset` option: `st-flash write --reset` results in two subsequent reset signals on the `NRST` line -# Using STM32 discovery kits with open source tools +Depending on the used programmer the hardware reset line is not always connected. +This is especially the case for low-cost STLINK/V2 clone programmers. +Here the SWD connector consists of only 4 pins: `VCC`, `SWCLK`, `GND` and `SWDATA`. -This guide details the use of STMicroelectronics STM32 discovery kits in an open source environment. +When the physical reset line `NRST` is not connected, a reset is initiated by software via `SWD_SWDIO/JTAG_TMS` (software reset). +Just as mentioned above, flashing is possible here eiher with and without the `--reset` option. -## Installing a GNU toolchain +Configuring the STM32 pin `JTAG_TMS/SWD_SWDIO` as an output now also prevents the SWD interface from flashing and resetting the device. +In consequence this constellation typically requires a _hard reset_ to allow for the ST-Link/V2 programmer to reconnect to the target at all. -Any toolchain supporting the cortex m3 should do. +As soon as the device is in DFU mode, the `JTAG_TMS/SWD_SWDIO` pin is left in the default state with all JTAG pins available. +Here flashing of the device is now possible with and without the `--reset` option. + +The debug command `(gdb) monitor jtag_reset` sends a _hard reset_ signal via the `NRST` pin to reset the device and allows for flashing it (again). + +--- + +( Content below is currently unrevised and may be outdated as of Mar 2021. ) ## Using the GDB server @@ -200,7 +240,6 @@ Of course, you can use this instead of the gdb server, if you prefer. Just remember to use the “.bin” image, rather than the .elf file. ``` - # write blink.bin into FLASH $> [sudo] ./st-flash write fancy_blink.bin 0x08000000 ``` @@ -226,7 +265,7 @@ There are a few options: -m, --multi Set gdb server to extended mode. st-util will continue listening for connections after disconnect. - -n, --no-reset + -n, --no-reset, --hot-plug Do not reset board on connection. ``` @@ -272,7 +311,7 @@ In order to continue, one can use 'monitor reset' to reset the MCU. Remember that you can shorten the commands. `tar ext :4242` is good enough for GDB. -If you need to send a hard reset signal through `NRST` pin, you can use the following command: +If you need to send a reset signal, you can use the following command: ``` (gdb) monitor jtag_reset diff --git a/doc/version_support.md b/doc/version_support.md index afa2d2bd7..5d2cdd375 100644 --- a/doc/version_support.md +++ b/doc/version_support.md @@ -1,8 +1,7 @@ - _Source:_ pkgs.org - [libusb](https://pkgs.org/search/?q=libusb); [cmake](https://pkgs.org/search/?q=cmake); [gtk](https://pkgs.org/search/?q=gtk) (as of Apr 2020) - ## Supported Operating Systems + ### Microsoft Windows On Windows users should ensure that cmake 3.17.0 is installed.
@@ -10,72 +9,69 @@ Up on compiling c-make will check **automatically**, whether `libusb` 1.0.20 or If this is not the case, the installation routine will download the latest version (1.0.23 at the time of writing).
Thus no user interaction regarding libusb is necessary. -* Windows 10 -* Windows 8.1 - +- Windows 10 +- Windows 8.1 ### Apple macOS | Package Repository | libusb
version | cmake
version | gtk-3
version | Supported macOS versions | -| --- | --- | --- | --- | --- | -| homebrew | 1.0.23 | 3.17.0 | 3.24.18
gtk+3 | 10.12 (Sierra)- 10.15 (Catalina) | -| MacPorts | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | 10.6 (Snow Leopard) - 10.15 (Catalina) | - -NOTE: In order to use a STLINK/v1 programmer on macOS, versions 10.14 or 10.15 are required. +| ------------------ | ------------------- | ------------------ | ------------------ | ------------------------ | +| homebrew | 1.0.23 | 3.17.0 | 3.24.18
gtk+3 | 10.9 - 10.15 | +| MacPorts | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | 10.4 - 10.15 | +NOTE: In order to use a STLINK/V1 programmer on macOS, versions 10.14 or 10.15 are required. ### Linux-/Unix-based: -| Operating System | libusb
version | cmake
version | gtk-3
version | Notes | -| --- | --- | --- | --- | --- | -| Alpine Edge | 1.0.23 | 3.17.0 | 3.99.0
gtk+3.0 | | -| ALT Linux Sisyphus | 1.0.23 | 3.17.0 | 3.24.18
libgtk+3 | | -| Arch Linux | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | | -| Fedora Rawhide | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | | named `libusbx`, but
`libusb`-codebase is used | -| KaOS | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | | -| OpenMandriva Cooker | 1.0.23 | 3.17.0 | 3.24.18
libgtk+3.0
lib64gtk+3.0 | | -| PCLinuxOS | 1.0.23
lib64usb1.0 | 3.17.0 | 3.24.18
lib64gtk+3.0 | | -| Slackware Current | 1.0.23 | 3.17.0 | 3.24.18
gtk+3 | | -| Solus | 1.0.23 | 3.16.5 | 3.24.16
libgtk-3 | | -| Debian Sid | 1.0.23 | 3.16.3 | 3.24.18
libgtk-3 | | -| OpenMandriva Lx 4.1 | 1.0.23 | 3.16.3 | 3.24.13
libgtk+3.0
lib64gtk+3.0 | | -| Ubuntu 20.04 LTS (Focal Fossa) | 1.0.23 | 3.16.3 | 3.24.17
libgtk-3 | | -| openSUSE Tumbleweed | 1.0.23 | 3.16.2 | 3.24.16
gtk3 | | -| Alpine 3.11 | 1.0.23 | 3.15.5 | 3.24.13
gtk+3.0 | | -| Ubuntu 19.10 (Eoan Ermine) | 1.0.23 | 3.13.4 | 3.24.12
libgtk-3 | | -| Mageia Cauldron | 1.0.22 | 3.17.0 | 3.24.18
libgtk+3.0
lib64gtk+3.0 | | -| NetBSD 9.0 | 1.0.22 | 3.16.1 | 3.24.12
gtk+3 | | -| NetBSD 8.1 | 1.0.22 | 3.16.1 | 3.24.12
gtk+3 | | -| NetBSD 7.2 | 1.0.22 | 3.16.1 | _N/A_ | | -| Alpine 3.10 | 1.0.22 | 3.14.5 | 3.24.8
gtk+3.0 | | -| Fedora 31 | 1.0.22 | 3.14.5 | 3.24.12
gtk3 | named `libusbx`, but
`libusb`-codebase is used | -| Mageia 7.1 | 1.0.22 | 3.14.3 | 3.24.8
libgtk+3.0
lib64gtk+3.0 | | -| Fedora 30 | 1.0.22 | 3.14.2 | 3.24.8
gtk3 | named `libusbx`, but
`libusb`-codebase is used | -| Debian 10 (Buster) | 1.0.22 | 3.13.4 | 3.24.5
libgtk-3 | | -| Alpine 3.9 | 1.0.22 | 3.13.0 | 3.24.1
gtk+3.0 | | -| CentOS 8 | 1.0.22 | 3.11.4 | 3.22.30
gtk3 | named `libusbx`, but
`libusb`-codebase is used | -| openSUSE Leap 15.2 | 1.0.21 | 3.15.5 | 3.24.14
gtk3 | | -| openSUSE Leap 15.1 | 1.0.21 | 3.10.2 | 3.22.30
gtk3 | | -| Ubuntu 18.04 LTS (Bionic Beaver) | 1.0.21 | 3.10.2 | 3.22.30
libgtk-3 | | -| Debian 9 (Stretch) | 1.0.21 | 3.7.2 | 3.22.11
libgtk-3 | | -| Slackware 14.2 | **1.0.20** | 3.5.2 | 3.18.9
gtk+3 | | -| Ubuntu 16.04 LTS (Xenial Xerus) | **1.0.20** | 3.5.1 | 3.18.9
libgtk-3 | | -| OpenMandriva Lx 3.0 | **1.0.20** | **3.4.2** | 3.18.9
libgtk+3.0
lib64gtk+3.0 | | -| FreeBSD 13 | **1.0.16** - 1.0.18 | 3.15.5 | 3.24.10
gtk3 | linux_libusb-13.0r358841
(integrated) | -| FreeBSD 12 | **1.0.16** - 1.0.18 | 3.15.5 | 3.24.10
gtk3 | linux_libusb-11.0r261448_4
(integrated) | -| FreeBSD 11 | **1.0.16** - 1.0.18 | 3.15.5 | 3.24.10
gtk3 | linux_libusb-11.0r261448_4
(integrated) | - +| Operating System | libusb
version | cmake
version | gtk-3
version | Notes | +| -------------------------------- | ----------------------- | ------------------ | ----------------------------------------- | ----------------------------------------------------------------------------- | +| Alpine Edge | 1.0.23 | 3.17.0 | 3.99.0
gtk+3.0 | | +| ALT Linux Sisyphus | 1.0.23 | 3.17.0 | 3.24.18
libgtk+3 | | +| Arch Linux | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | | +| Fedora Rawhide | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | named `libusbx`, but
`libusb`-codebase is used | +| KaOS | 1.0.23 | 3.17.0 | 3.24.18
gtk3 | | +| OpenMandriva Cooker | 1.0.23 | 3.17.0 | 3.24.18
libgtk+3.0
lib64gtk+3.0 | | +| PCLinuxOS | 1.0.23
lib64usb1.0 | 3.17.0 | 3.24.18
lib64gtk+3.0 | | +| Slackware Current | 1.0.23 | 3.17.0 | 3.24.18
gtk+3 | | +| Solus | 1.0.23 | 3.16.5 | 3.24.16
libgtk-3 | | +| Debian Sid | 1.0.23 | 3.16.3 | 3.24.18
libgtk-3 | | +| OpenMandriva Lx 4.1 | 1.0.23 | 3.16.3 | 3.24.13
libgtk+3.0
lib64gtk+3.0 | | +| Ubuntu 20.04 LTS (Focal Fossa) | 1.0.23 | 3.16.3 | 3.24.17
libgtk-3 | | +| openSUSE Tumbleweed | 1.0.23 | 3.16.2 | 3.24.16
gtk3 | | +| Alpine 3.11 | 1.0.23 | 3.15.5 | 3.24.13
gtk+3.0 | | +| Ubuntu 19.10 (Eoan Ermine) | 1.0.23 | 3.13.4 | 3.24.12
libgtk-3 | | +| Mageia Cauldron | 1.0.22 | 3.17.0 | 3.24.18
libgtk+3.0
lib64gtk+3.0 | | +| NetBSD 9.0 | 1.0.22 | 3.16.1 | 3.24.12
gtk+3 | | +| NetBSD 8.1 | 1.0.22 | 3.16.1 | 3.24.12
gtk+3 | | +| NetBSD 7.2 | 1.0.22 | 3.16.1 | _N/A_ | | +| Alpine 3.10 | 1.0.22 | 3.14.5 | 3.24.8
gtk+3.0 | | +| Fedora 31 | 1.0.22 | 3.14.5 | 3.24.12
gtk3 | named `libusbx`, but
`libusb`-codebase is used | +| Mageia 7.1 | 1.0.22 | 3.14.3 | 3.24.8
libgtk+3.0
lib64gtk+3.0 | | +| Fedora 30 | 1.0.22 | 3.14.2 | 3.24.8
gtk3 | named `libusbx`, but
`libusb`-codebase is used | +| Debian 10 (Buster) | 1.0.22 | 3.13.4 | 3.24.5
libgtk-3 | | +| Alpine 3.9 | 1.0.22 | 3.13.0 | 3.24.1
gtk+3.0 | | +| CentOS 8 | 1.0.22 | 3.11.4 | 3.22.30
gtk3 | named `libusbx`, but
`libusb`-codebase is used | +| openSUSE Leap 15.2 | 1.0.21 | 3.15.5 | 3.24.14
gtk3 | | +| openSUSE Leap 15.1 | 1.0.21 | 3.10.2 | 3.22.30
gtk3 | | +| Ubuntu 18.04 LTS (Bionic Beaver) | 1.0.21 | 3.10.2 | 3.22.30
libgtk-3 | | +| Debian 9 (Stretch) | 1.0.21 | 3.7.2 | 3.22.11
libgtk-3 | | +| Slackware 14.2 | 1.0.20 | 3.5.2 | 3.18.9
gtk+3 | | +| Ubuntu 16.04 LTS (Xenial Xerus) | 1.0.20 | 3.5.1 | 3.18.9
libgtk-3 | | +| OpenMandriva Lx 3.0x | 1.0.20 | **3.4.2** | 3.18.9
libgtk+3.0
lib64gtk+3.0 | | +| FreeBSD 13 | **1.0.16 - 1.0.18** | 3.15.5 | 3.24.10
gtk3 | linux_libusb-13.0r358841
LIBUSB_API_VERSION 0x01000102
(integrated) | +| FreeBSD 12 | **1.0.16 - 1.0.18** | 3.15.5 | 3.24.10
gtk3 | linux_libusb-13.0r358841
LIBUSB_API_VERSION 0x01000102
(integrated) | +| FreeBSD 11 | **1.0.16 - 1.0.18** | 3.15.5 | 3.24.10
gtk3 | linux_libusb-13.0r358841
LIBUSB_API_VERSION 0x01000102
(integrated) | ## Unsupported Operating Systems (as of Release v1.6.1) -| Operating System | libusb
version | cmake
version | End of
OS-Support | Notes | -| --- | --- | --- | --- | --- | -| CentOS 7 | 1.0.21 | **2.8.12.2** | | named `libusbx`, but
`libusb`-codebase is used | -| Debian 8 (Jessie) | 1.0.**19** | 3.**0.2** | Jun 2020 | -| Ubuntu 14.04 LTS (Trusty Tahr) | 1.0.**17** | **2.8.12.2** | Apr 2019 | -| CentOS 6 | 1.0.**9** | **2.8.12.2** | Dec 2020 | named `libusbx`, but
`libusb`-codebase is used | -| Slackware 14.1 | 1.0.**9** | **2.8.12** | | -| Slackware 14.0 | 1.0.**9** | **2.8.8** | | +| Operating System | libusb
version | cmake
version | End of
OS-Support | Notes | +| ------------------------------ | ------------------- | ------------------ | ---------------------- | --------------------------------------------------- | +| CentOS 7 | 1.0.21 | **2.8.12.2** | | named `libusbx`, but
`libusb`-codebase is used | +| Debian 8 (Jessie) | 1.0.19 | **3.0.2** | Jun 2020 | +| Ubuntu 14.04 LTS (Trusty Tahr) | 1.0.17 | **2.8.12.2** | Apr 2019 | +| CentOS 6 | 1.0.**9** | **2.8.12.2** | Dec 2020 | named `libusbx`, but
`libusb`-codebase is used | +| Slackware 14.1 | 1.0.**9** | **2.8.12** | | +| Slackware 14.0 | 1.0.**9** | **2.8.8** | | _All other operating systems which are not listed are unsupported._ diff --git a/flashloaders/Makefile b/flashloaders/Makefile index 7b17cb2a0..8b01d5293 100644 --- a/flashloaders/Makefile +++ b/flashloaders/Makefile @@ -1,38 +1,38 @@ -# Note that according to the original GPLed code, compiling is noted to be -# as simple as gcc -c, this fails with my tests where this will lead to a wrong -# address read by the program. -# This makefile will save your time from dealing with compile errors -# Adjust CC if needed +# The flash loader code cannot be compiled by the system gcc. This +# makefile use arm-none-eabi-gcc for this purpose -CC = /opt/local/gcc-arm-none-eabi-8-2018-q4-major/bin/arm-none-eabi-gcc +CROSS_COMPILE ?= arm-none-eabi- -CFLAGS_thumb1 = -mcpu=Cortex-M0 -Tlinker.ld -ffreestanding -nostdlib -CFLAGS_thumb2 = -mcpu=Cortex-M3 -Tlinker.ld -ffreestanding -nostdlib +CC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy -all: stm32vl.o stm32f0.o stm32l.o stm32f4.o stm32f4_lv.o stm32l4.o stm32f7.o stm32f7_lv.o +XXD = xxd +XXDFLAGS = -i -c 4 -stm32vl.o: stm32f0.s - $(CC) stm32f0.s $(CFLAGS_thumb2) -o stm32vl.o -stm32f0.o: stm32f0.s - $(CC) stm32f0.s $(CFLAGS_thumb1) -o stm32f0.o -stm32l.o: stm32lx.s - $(CC) stm32lx.s $(CFLAGS_thumb2) -o stm32l.o -stm32f4.o: stm32f4.s - $(CC) stm32f4.s $(CFLAGS_thumb2) -o stm32f4.o -stm32f4_lv.o: stm32f4lv.s - $(CC) stm32f4lv.s $(CFLAGS_thumb2) -o stm32f4_lv.o -stm32l4.o: stm32l4.s - $(CC) stm32l4.s $(CFLAGS_thumb2) -o stm32l4.o -stm32f7.o: stm32f7.s - $(CC) stm32f7.s $(CFLAGS_thumb2) -o stm32f7.o -stm32f7_lv.o: stm32f7lv.s - $(CC) stm32f7lv.s $(CFLAGS_thumb2) -o stm32f7_lv.o +CFLAGS_ARMV6_M = -mcpu=Cortex-M0 -Tlinker.ld -ffreestanding -nostdlib +CFLAGS_ARMV7_M = -mcpu=Cortex-M3 -Tlinker.ld -ffreestanding -nostdlib -clean: - rm *.o +all: stm32vl.h stm32f0.h stm32lx.h stm32f4.h stm32f4lv.h stm32l4.h stm32f7.h stm32f7lv.h + +%.h: %.bin + $(XXD) $(XXDFLAGS) $< $@ +%.bin: %.o + $(OBJCOPY) -O binary $< $@ + rm $< +# separate rule for STM32F0 +stm32f0.o: stm32f0.s + $(CC) stm32f0.s $(CFLAGS_ARMV6_M) -o stm32f0.o +# separate rule for STM32F1/F3 +stm32vl.o: stm32f0.s + $(CC) stm32f0.s $(CFLAGS_ARMV7_M) -o stm32vl.o +# generic rule for all other ARMv7-M +%.o: %.s + $(CC) $< $(CFLAGS_ARMV7_M) -o $@ +clean: + rm -f *.h diff --git a/flashloaders/cleanroom.md b/flashloaders/cleanroom.md index a468efe49..b2cb9f00d 100644 --- a/flashloaders/cleanroom.md +++ b/flashloaders/cleanroom.md @@ -1,6 +1,4 @@ -Original Chinese version can be found below. - -# Clean Room Documentation English Version +# Flash Loader Documentation Code is situated in section `.text` @@ -12,11 +10,12 @@ All parameters would be passed over registers `r0`: the base address of the copy source `r1`: the base address of the copy destination -`r2`: the total word (4 bytes) count to be copied (with expeptions) +`r2`: the count of byte to be copied +`r3`: flash register offset (used to support two banks) **What the program is expected to do**: -Copy data from source to destination, after which trigger a breakpint to exit. Before exit, `r2` must be cleared to zero to indicate that the copy is done. +Copy data from source to destination, after which trigger a breakpint to exit. Before exit, `r2` must be less or equal to zero to indicate that the copy is done. **Limitation**: No stack operations are permitted. Registers ranging from `r3` to `r12` are free to use. Note that `r13` is `sp`(stack pointer), `r14` is `lr`(commonly used to store jump address), `r15` is `pc`(program counter). @@ -24,8 +23,6 @@ Copy data from source to destination, after which trigger a breakpint to exit. B ## stm32f0.s -**Exception**: `r2` stores the total half word (2 bytes) count to be copied - `flash_base`: 0x40022000 `FLASH_CR`: offset from `flash_base` is 16 @@ -37,11 +34,11 @@ Copy data from source to destination, after which trigger a breakpint to exit. B **Special requirements**: -Before every copy, read a word from FLASH_CR, set the lowest bit to 1 and write back. Copy one half word each time. +Before every copy, read a word from FLASH_CR, set the PG bit to 1 and write back. Copy one half word each time. -How to wait for the write process: read a word from FLASH_SR, loop until the content is not 1. After that, check FLASH_SR, proceed if the content is 4, otherwise exit. +How to wait for the write process: read a word from FLASH_SR, loop until the busy bit is reset. After that, FLASH_SR is check. The process is interrupted if the error bit (0x04) is set. -Exit: after the copying process and before triggering the breakpoint, clear the lowest bit in FLASH_CR. +Exit: after the copying process and before triggering the breakpoint, clear the PG bit in FLASH_CR. ## stm32f4.s @@ -56,7 +53,8 @@ Exit: after the copying process and before triggering the breakpoint, clear the **Special requirements**: Copy one word each time. -How to wait for the write process: read a half word from FLASH_SR, loop until the content is not 1. + +How to wait for the write process: read a word from FLASH_SR, loop until the busy bit is reset. ## stm32f4lv.s @@ -71,7 +69,7 @@ How to wait for the write process: read a half word from FLASH_SR, loop until th Copy one byte each time. -How to wait from the write process: read a half word from FLASH_SR, loop until the content is not 1. +How to wait from the write process: read a half word from FLASH_SR, loop until the busy bit is reset. ## stm32f7.s @@ -89,7 +87,7 @@ Mostly same with `stm32f4.s`. Require establishing a memory barrier after every Mostly same with `stm32f7.s`. Copy one byte each time. -## stm32l0x.s +## stm32lx.s **Special Requirements**: @@ -97,8 +95,6 @@ Copy one word each time. No wait for write. ## stm32l4.s -**Exception**: r2 stores the double word count to be copied. - `flash_base`: 0x40022000 `FLASH_BSY`: offset from `flash_base` is 0x12 @@ -109,14 +105,10 @@ Copy one word each time. No wait for write. Copy one double word each time (More than one registers are allowed). -How to wait for the write process: read a half word from `FLASH_BSY`, loop until the lowest bit turns non-1. - -## stm32lx.s +How to wait for the write process: read a half word from `FLASH_BSY`, loop until the busy bit is reset. -Same with stm32l0x.s. - -# 净室工程文档-原始中文版 +# 净室工程文档-原始中文版 (out of date) 代码位于的section:`.text` 编译制导添加`.syntax unified` @@ -139,8 +131,6 @@ Same with stm32l0x.s. ## stm32f0.s -例外:`r2`:拷贝half word(2字节)数 - 特殊地址定义:`flash_base`:定义为0x40022000 `FLASH_CR`: 相对`flash_base`的offset为16 @@ -230,4 +220,4 @@ Same with stm32l0x.s. ## stm32lx.s -要求与stm32l0x.s相同 \ No newline at end of file +要求与stm32l0x.s相同 diff --git a/flashloaders/stm32f0.s b/flashloaders/stm32f0.s index f30e4bfc6..23f1c43fe 100644 --- a/flashloaders/stm32f0.s +++ b/flashloaders/stm32f0.s @@ -1,6 +1,14 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: /* @@ -17,54 +25,54 @@ copy: */ nop nop - ldr r7, =flash_base - ldr r4, [r7] - ldr r7, =flash_off_cr - ldr r6, [r7] - adds r6, r6, r4 - ldr r7, =flash_off_sr - ldr r5, [r7] - adds r5, r5, r4 -loop: - # FLASH_CR ^= 1 - ldr r7, =0x1 - ldr r3, [r6] - orrs r3, r3, r7 - str r3, [r6] + # load flash control register address + # add r3 to flash_base for support dual bank (see flash_loader.c) + ldr r7, flash_base + add r7, r7, r3 + ldr r6, flash_off_cr + add r6, r6, r7 + ldr r5, flash_off_sr + add r5, r5, r7 + # FLASH_CR = 0x01 (set PG) + ldr r4, =0x1 + str r4, [r6] + +loop: # copy 2 bytes - ldrh r3, [r0] - strh r3, [r1] + ldrh r4, [r0] + strh r4, [r1] - ldr r7, =2 - adds r0, r0, r7 - adds r1, r1, r7 + # increment address + adds r0, r0, #0x2 + adds r1, r1, #0x2 - # wait if FLASH_SR == 1 + # BUSY flag + ldr r7, =0x01 wait: - ldr r7, =0x1 - ldr r3, [r5] - tst r3, r7 - beq wait + # get FLASH_SR + ldr r4, [r5] - # exit if FLASH_SR != 4 - ldr r7, =0x4 - tst r3, r7 + # wait until BUSY flag is reset + tst r4, r7 + bne wait + + # test PGERR or WRPRTERR flag is reset + ldr r7, =0x14 + tst r4, r7 bne exit - # loop if r2 != 0 - ldr r7, =0x1 - subs r2, r2, r7 - cmp r2, #0 - bne loop + # loop if count > 0 + subs r2, r2, #0x2 + bgt loop exit: # FLASH_CR &= ~1 ldr r7, =0x1 - ldr r3, [r6] - bics r3, r3, r7 - str r3, [r6] + ldr r4, [r6] + bics r4, r4, r7 + str r4, [r6] bkpt diff --git a/flashloaders/stm32f4.s b/flashloaders/stm32f4.s index a88ad9e02..a66c70dac 100644 --- a/flashloaders/stm32f4.s +++ b/flashloaders/stm32f4.s @@ -1,6 +1,14 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base @@ -9,22 +17,24 @@ copy: loop: # copy 4 bytes - ldr r3, [r0] - str r3, [r1] + ldr r4, [r0] + str r4, [r1] + # increment address add r0, r0, #4 add r1, r1, #4 - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #4 + bgt loop exit: bkpt diff --git a/flashloaders/stm32f4lv.s b/flashloaders/stm32f4lv.s index 41467a9ef..b8fcfa048 100644 --- a/flashloaders/stm32f4lv.s +++ b/flashloaders/stm32f4lv.s @@ -1,36 +1,40 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base ldr r10, flash_off_sr add r10, r10, r12 - # tip 1: original r2 indicates the count of 4 bytes need to copy, - # but we can only copy one byte each time. - # as we have no flash larger than 1GB, we do a little trick here. - # tip 2: r2 is always a power of 2 - mov r2, r2, lsl#2 - loop: # copy 1 byte - ldrb r3, [r0] - strb r3, [r1] + ldrb r4, [r0] + strb r4, [r1] + # increment address add r0, r0, #1 add r1, r1, #1 - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #1 + bgt loop exit: bkpt diff --git a/flashloaders/stm32f7.s b/flashloaders/stm32f7.s index 3779a5ea6..4b43cebdc 100644 --- a/flashloaders/stm32f7.s +++ b/flashloaders/stm32f7.s @@ -1,6 +1,14 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base @@ -9,25 +17,27 @@ copy: loop: # copy 4 bytes - ldr r3, [r0] - str r3, [r1] + ldr r4, [r0] + str r4, [r1] + # increment address add r0, r0, #4 add r1, r1, #4 # memory barrier dsb sy - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #4 + bgt loop exit: bkpt diff --git a/flashloaders/stm32f7lv.s b/flashloaders/stm32f7lv.s index e7b66cc2c..78ff35dbc 100644 --- a/flashloaders/stm32f7lv.s +++ b/flashloaders/stm32f7lv.s @@ -1,39 +1,43 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base ldr r10, flash_off_sr add r10, r10, r12 - # tip 1: original r2 indicates the count in 4 bytes need to copy, - # but we can only copy one byte each time. - # as we have no flash larger than 1GB, we do a little trick here. - # tip 2: r2 is always a power of 2 - mov r2, r2, lsl#2 - loop: # copy 1 byte - ldrb r3, [r0] - strb r3, [r1] + ldrb r4, [r0] + strb r4, [r1] + # increment address add r0, r0, #1 add r1, r1, #1 # memory barrier dsb sy - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #1 + bgt loop exit: bkpt diff --git a/flashloaders/stm32l0x.s b/flashloaders/stm32l0x.s deleted file mode 100644 index f9c257e2e..000000000 --- a/flashloaders/stm32l0x.s +++ /dev/null @@ -1,22 +0,0 @@ - .syntax unified - .text - - .global copy -copy: -loop: - # copy 4 bytes - ldr r3, [r0] - str r3, [r1] - - ldr r7, =4 - add r0, r0, r7 - add r1, r1, r7 - - # loop if r2 != 0 - ldr r7, =1 - subs r2, r2, r7 - cmp r2, #0 - bne loop - -exit: - bkpt diff --git a/flashloaders/stm32l4.s b/flashloaders/stm32l4.s index 32c27a057..50676be9a 100644 --- a/flashloaders/stm32l4.s +++ b/flashloaders/stm32l4.s @@ -1,32 +1,42 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base - ldr r10, flash_off_bsy + ldr r10, flash_off_sr add r10, r10, r12 loop: # copy 8 bytes - ldr r3, [r0] + ldr r5, [r0] ldr r4, [r0, #4] - str r3, [r1] + str r5, [r1] str r4, [r1, #4] + # increment address add r0, r0, #8 add r1, r1, #8 - # wait if FLASH_BSY[0b] == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait + # get FLASH_SR + ldr r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x10000 + bne wait - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # loop if count > 0 + subs r2, r2, #8 + bgt loop exit: bkpt @@ -34,5 +44,5 @@ exit: .align 2 flash_base: .word 0x40022000 -flash_off_bsy: - .word 0x12 +flash_off_sr: + .word 0x10 diff --git a/flashloaders/stm32lx.s b/flashloaders/stm32lx.s index f9c257e2e..69acdea7b 100644 --- a/flashloaders/stm32lx.s +++ b/flashloaders/stm32lx.s @@ -1,22 +1,28 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: loop: # copy 4 bytes - ldr r3, [r0] - str r3, [r1] + ldr r4, [r0] + str r4, [r1] - ldr r7, =4 - add r0, r0, r7 - add r1, r1, r7 + # increment address + add r0, r0, #4 + add r1, r1, #4 - # loop if r2 != 0 - ldr r7, =1 - subs r2, r2, r7 - cmp r2, #0 - bne loop + # loop if count > 0 + subs r2, r2, #4 + bgt loop exit: bkpt diff --git a/inc/backend.h b/inc/backend.h index ebd438127..a45dccd82 100644 --- a/inc/backend.h +++ b/inc/backend.h @@ -10,7 +10,7 @@ int (*core_id) (stlink_t * stl); int (*reset) (stlink_t * stl); int (*jtag_reset) (stlink_t * stl, int value); - int (*run) (stlink_t * stl); + int (*run) (stlink_t * stl, enum run_type type); int (*status) (stlink_t * stl); int (*version) (stlink_t *sl); int (*read_debug32) (stlink_t *sl, uint32_t addr, uint32_t *data); diff --git a/inc/stlink.h b/inc/stlink.h index 9b5e56594..ec119c145 100644 --- a/inc/stlink.h +++ b/inc/stlink.h @@ -58,6 +58,11 @@ enum target_state { #define STLINK_JTAG_READDEBUG_32BIT 0x36 #define STLINK_JTAG_DRIVE_NRST 0x3C +/* NRST pin states */ +#define STLINK_JTAG_DRIVE_NRST_LOW 0x00 +#define STLINK_JTAG_DRIVE_NRST_HIGH 0x01 +#define STLINK_JTAG_DRIVE_NRST_PULSE 0x02 + #define STLINK_DEBUG_APIV2_SWD_SET_FREQ 0x43 #define STLINK_APIV3_SET_COM_FREQ 0x61 @@ -79,7 +84,8 @@ enum target_state { #define STLINK_SWDCLK_15KHZ_DIVISOR 265 #define STLINK_SWDCLK_5KHZ_DIVISOR 798 -#define STLINK_SERIAL_MAX_SIZE 64 +#define STLINK_SERIAL_LENGTH 24 +#define STLINK_SERIAL_BUFFER_SIZE (STLINK_SERIAL_LENGTH + 1) #define STLINK_V3_MAX_FREQ_NB 10 @@ -136,6 +142,8 @@ typedef uint32_t stm32_addr_t; typedef struct flash_loader { stm32_addr_t loader_addr; // loader sram addr stm32_addr_t buf_addr; // buffer sram address + uint32_t rcc_dma_bkp; // backup RCC DMA enable state + uint32_t iwdg_kr; // IWDG key register address } flash_loader_t; typedef struct _cortex_m3_cpuid_ { @@ -170,6 +178,25 @@ enum transport_type { TRANSPORT_TYPE_INVALID }; +enum connect_type { + CONNECT_HOT_PLUG = 0, + CONNECT_NORMAL = 1, + CONNECT_UNDER_RESET = 2, +}; + +enum reset_type { + RESET_AUTO = 0, + RESET_HARD = 1, + RESET_SOFT = 2, + RESET_SOFT_AND_HALT = 3, +}; + +enum run_type { + RUN_NORMAL = 0, + RUN_FLASH_LOADER = 1, +}; + + typedef struct _stlink stlink_t; #include @@ -191,8 +218,7 @@ struct _stlink { uint32_t chip_id; // set by stlink_load_device_params(), used to identify flash and sram enum target_state core_stat; // set by stlink_status() - char serial[STLINK_SERIAL_MAX_SIZE]; - int serial_size; + char serial[STLINK_SERIAL_BUFFER_SIZE]; int freq; // set by stlink_open_usb(), values: STLINK_SWDCLK_xxx_DIVISOR enum stlink_flash_type flash_type; @@ -229,10 +255,8 @@ int stlink_exit_debug_mode(stlink_t *sl); int stlink_exit_dfu_mode(stlink_t *sl); void stlink_close(stlink_t *sl); int stlink_core_id(stlink_t *sl); -int stlink_reset(stlink_t *sl); -int stlink_jtag_reset(stlink_t *sl, int value); -int stlink_soft_reset(stlink_t *sl, int halt_on_reset); -int stlink_run(stlink_t *sl); +int stlink_reset(stlink_t *sl, enum reset_type type); +int stlink_run(stlink_t *sl, enum run_type type); int stlink_status(stlink_t *sl); int stlink_version(stlink_t *sl); int stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data); @@ -297,7 +321,9 @@ int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr int stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl); int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t addr, uint8_t* base, uint32_t len); -int stlink_flashloader_stop(stlink_t *sl); +int stlink_flashloader_stop(stlink_t *sl, flash_loader_t *fl); + +int stlink_target_connect(stlink_t *sl, enum connect_type connect); #include #include diff --git a/inc/stm32.h b/inc/stm32.h index ca56a12f5..21da2f563 100644 --- a/inc/stm32.h +++ b/inc/stm32.h @@ -10,21 +10,29 @@ /* Cortex core ids */ #define STM32VL_CORE_ID 0x1ba01477 #define STM32F7_CORE_ID 0x5ba02477 -#define STM32H7_CORE_ID 0x6ba02477 // STM32H7 JTAG ID Code (RM0433 pg3065) +#define STM32H7_CORE_ID 0x6ba02477 // STM32H7 SWD ID Code +#define STM32H7_CORE_ID_JTAG 0x6ba00477 // STM32H7 JTAG ID Code (RM0433 pg3065) /* Constant STM32 memory map figures */ -#define STM32_FLASH_BASE ((uint32_t)0x08000000) -#define STM32_F1_FLASH_BANK2_BASE ((uint32_t)0x08080000) -#define STM32_H7_FLASH_BANK2_BASE ((uint32_t)0x08100000) -#define STM32_SRAM_BASE ((uint32_t)0x20000000) -#define STM32_G0_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800) -#define STM32_G4_OPTION_BYTES_BASE ((uint32_t)0x1FFFF800) -#define STM32_L0_CATx_OPTION_BYTES_BASE ((uint32_t)0x1FF80000) +#define STM32_SRAM_BASE ((uint32_t)0x20000000) +#define STM32_FLASH_BASE ((uint32_t)0x08000000) +#define STM32_F1_FLASH_BANK2_BASE ((uint32_t)0x08080000) +#define STM32_H7_FLASH_BANK2_BASE ((uint32_t)0x08100000) + #define STM32_F2_OPTION_BYTES_BASE ((uint32_t)0x1FFFC000) -#define STM32_L4_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800) -#define STM32_L1_OPTION_BYTES_BASE ((uint32_t)0x1FF80000) #define STM32_F4_OPTION_BYTES_BASE ((uint32_t)0x40023C14) #define STM32_F7_OPTION_BYTES_BASE ((uint32_t)0x1FFF0000) #define STM32_H7_OPTION_BYTES_BASE ((uint32_t)0x5200201C) +#define STM32_G0_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800) +#define STM32_L4_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800) + +#define STM32_L0_OPTION_BYTES_BASE ((uint32_t)0x1FF80000) +#define STM32_L1_OPTION_BYTES_BASE ((uint32_t)0x1FF80000) + +#define STM32_F0_OPTION_BYTES_BASE ((uint32_t)0x1FFFF800) +#define STM32_F1_OPTION_BYTES_BASE ((uint32_t)0x1FFFF800) +#define STM32_F3_OPTION_BYTES_BASE ((uint32_t)0x1FFFF800) +#define STM32_G4_OPTION_BYTES_BASE ((uint32_t)0x1FFFF800) + #endif // STM32_H diff --git a/src/common.c b/src/common.c index 99049196d..4541aa31c 100644 --- a/src/common.c +++ b/src/common.c @@ -1,20 +1,20 @@ #define DEBUG_FLASH 0 #include +#include #include #include #include -#include #include -#include #include -#include #include +#include +#include -#include +#include #include #include -#include +#include #ifdef STLINK_HAVE_SYS_MMAN_H #include @@ -35,7 +35,8 @@ /* stm32f FPEC flash controller interface, pm0063 manual */ // TODO - all of this needs to be abstracted out.... -// STM32F05x is identical, based on RM0091 (DM00031936, Doc ID 018940 Rev 2, August 2012) +// STM32F05x is identical, based on RM0091 (DM00031936, Doc ID 018940 Rev 2, +// August 2012) #define FLASH_REGS_ADDR 0x40022000 #define FLASH_REGS_SIZE 0x28 @@ -48,7 +49,8 @@ #define FLASH_OBR (FLASH_REGS_ADDR + 0x1c) #define FLASH_WRPR (FLASH_REGS_ADDR + 0x20) -// STM32F10x_XL has two flash memory banks with separate registers to control the second bank. +// STM32F10x_XL has two flash memory banks with separate registers to control +// the second bank. #define FLASH_KEYR2 (FLASH_REGS_ADDR + 0x44) #define FLASH_SR2 (FLASH_REGS_ADDR + 0x4c) #define FLASH_CR2 (FLASH_REGS_ADDR + 0x50) @@ -128,103 +130,112 @@ // Mostly the same as STM32G0 chips, but there are a few extra // registers because 'cat 3' devices can have two Flash banks. #define STM32G4_FLASH_REGS_ADDR (STM32Gx_FLASH_REGS_ADDR) -#define STM32G4_FLASH_PDKEYR (STM32G4_FLASH_REGS_ADDR + 0x04) -#define STM32G4_FLASH_PCROP1SR (STM32G4_FLASH_REGS_ADDR + 0x24) -#define STM32G4_FLASH_PCROP1ER (STM32G4_FLASH_REGS_ADDR + 0x28) -#define STM32G4_FLASH_WRP1AR (STM32G4_FLASH_REGS_ADDR + 0x2C) -#define STM32G4_FLASH_WRP1BR (STM32G4_FLASH_REGS_ADDR + 0x30) -#define STM32G4_FLASH_PCROP2SR (STM32G4_FLASH_REGS_ADDR + 0x44) -#define STM32G4_FLASH_PCROP2ER (STM32G4_FLASH_REGS_ADDR + 0x48) -#define STM32G4_FLASH_WRP2AR (STM32G4_FLASH_REGS_ADDR + 0x4C) -#define STM32G4_FLASH_WRP2BR (STM32G4_FLASH_REGS_ADDR + 0x50) -#define STM32G4_FLASH_SEC1R (STM32G4_FLASH_REGS_ADDR + 0x70) -#define STM32G4_FLASH_SEC2R (STM32G4_FLASH_REGS_ADDR + 0x74) +#define STM32G4_FLASH_PDKEYR (STM32G4_FLASH_REGS_ADDR + 0x04) +#define STM32G4_FLASH_PCROP1SR (STM32G4_FLASH_REGS_ADDR + 0x24) +#define STM32G4_FLASH_PCROP1ER (STM32G4_FLASH_REGS_ADDR + 0x28) +#define STM32G4_FLASH_WRP1AR (STM32G4_FLASH_REGS_ADDR + 0x2C) +#define STM32G4_FLASH_WRP1BR (STM32G4_FLASH_REGS_ADDR + 0x30) +#define STM32G4_FLASH_PCROP2SR (STM32G4_FLASH_REGS_ADDR + 0x44) +#define STM32G4_FLASH_PCROP2ER (STM32G4_FLASH_REGS_ADDR + 0x48) +#define STM32G4_FLASH_WRP2AR (STM32G4_FLASH_REGS_ADDR + 0x4C) +#define STM32G4_FLASH_WRP2BR (STM32G4_FLASH_REGS_ADDR + 0x50) +#define STM32G4_FLASH_SEC1R (STM32G4_FLASH_REGS_ADDR + 0x70) +#define STM32G4_FLASH_SEC2R (STM32G4_FLASH_REGS_ADDR + 0x74) // G0/G4 FLASH control register -#define STM32Gx_FLASH_CR_PG (0) /* Program */ -#define STM32Gx_FLASH_CR_PER (1) /* Page erase */ -#define STM32Gx_FLASH_CR_MER1 (2) /* Mass erase */ -#define STM32Gx_FLASH_CR_PNB (3) /* Page number */ -#define STM32G0_FLASH_CR_PNG_LEN (5) /* STM32G0: 5 page number bits */ -#define STM32G4_FLASH_CR_PNG_LEN (7) /* STM32G4: 7 page number bits */ -#define STM32Gx_FLASH_CR_MER2 (15) /* Mass erase (2nd bank)*/ -#define STM32Gx_FLASH_CR_STRT (16) /* Start */ -#define STM32Gx_FLASH_CR_OPTSTRT (17) /* Start of modification of option bytes */ -#define STM32Gx_FLASH_CR_FSTPG (18) /* Fast programming */ -#define STM32Gx_FLASH_CR_EOPIE (24) /* End of operation interrupt enable */ -#define STM32Gx_FLASH_CR_ERRIE (25) /* Error interrupt enable */ -#define STM32Gx_FLASH_CR_OBL_LAUNCH (27) /* Forces the option byte loading */ -#define STM32Gx_FLASH_CR_OPTLOCK (30) /* Options Lock */ -#define STM32Gx_FLASH_CR_LOCK (31) /* FLASH_CR Lock */ +#define STM32Gx_FLASH_CR_PG (0) /* Program */ +#define STM32Gx_FLASH_CR_PER (1) /* Page erase */ +#define STM32Gx_FLASH_CR_MER1 (2) /* Mass erase */ +#define STM32Gx_FLASH_CR_PNB (3) /* Page number */ +#define STM32G0_FLASH_CR_PNG_LEN (5) /* STM32G0: 5 page number bits */ +#define STM32G4_FLASH_CR_PNG_LEN (7) /* STM32G4: 7 page number bits */ +#define STM32Gx_FLASH_CR_MER2 (15) /* Mass erase (2nd bank)*/ +#define STM32Gx_FLASH_CR_STRT (16) /* Start */ +#define STM32Gx_FLASH_CR_OPTSTRT \ + (17) /* Start of modification of option bytes */ +#define STM32Gx_FLASH_CR_FSTPG (18) /* Fast programming */ +#define STM32Gx_FLASH_CR_EOPIE (24) /* End of operation interrupt enable */ +#define STM32Gx_FLASH_CR_ERRIE (25) /* Error interrupt enable */ +#define STM32Gx_FLASH_CR_OBL_LAUNCH (27) /* Forces the option byte loading */ +#define STM32Gx_FLASH_CR_OPTLOCK (30) /* Options Lock */ +#define STM32Gx_FLASH_CR_LOCK (31) /* FLASH_CR Lock */ // G0/G4 FLASH status register #define STM32Gx_FLASH_SR_ERROR_MASK (0x3fa) -#define STM32Gx_FLASH_SR_BSY (16) /* FLASH_SR Busy */ -#define STM32Gx_FLASH_SR_EOP (0) /* FLASH_EOP End of Operation */ +#define STM32Gx_FLASH_SR_PROGERR (3) +#define STM32Gx_FLASH_SR_WRPERR (4) +#define STM32Gx_FLASH_SR_PGAERR (5) +#define STM32Gx_FLASH_SR_BSY (16) /* FLASH_SR Busy */ +#define STM32Gx_FLASH_SR_EOP (0) /* FLASH_EOP End of Operation */ // G4 FLASH option register -#define STM32G4_FLASH_OPTR_DBANK (22) /* FLASH_OPTR Dual Bank Mode */ +#define STM32G4_FLASH_OPTR_DBANK (22) /* FLASH_OPTR Dual Bank Mode */ // WB (RM0434) #define STM32WB_FLASH_REGS_ADDR ((uint32_t)0x58004000) -#define STM32WB_FLASH_ACR (STM32WB_FLASH_REGS_ADDR + 0x00) -#define STM32WB_FLASH_KEYR (STM32WB_FLASH_REGS_ADDR + 0x08) -#define STM32WB_FLASH_OPT_KEYR (STM32WB_FLASH_REGS_ADDR + 0x0C) -#define STM32WB_FLASH_SR (STM32WB_FLASH_REGS_ADDR + 0x10) -#define STM32WB_FLASH_CR (STM32WB_FLASH_REGS_ADDR + 0x14) -#define STM32WB_FLASH_ECCR (STM32WB_FLASH_REGS_ADDR + 0x18) -#define STM32WB_FLASH_OPTR (STM32WB_FLASH_REGS_ADDR + 0x20) +#define STM32WB_FLASH_ACR (STM32WB_FLASH_REGS_ADDR + 0x00) +#define STM32WB_FLASH_KEYR (STM32WB_FLASH_REGS_ADDR + 0x08) +#define STM32WB_FLASH_OPT_KEYR (STM32WB_FLASH_REGS_ADDR + 0x0C) +#define STM32WB_FLASH_SR (STM32WB_FLASH_REGS_ADDR + 0x10) +#define STM32WB_FLASH_CR (STM32WB_FLASH_REGS_ADDR + 0x14) +#define STM32WB_FLASH_ECCR (STM32WB_FLASH_REGS_ADDR + 0x18) +#define STM32WB_FLASH_OPTR (STM32WB_FLASH_REGS_ADDR + 0x20) #define STM32WB_FLASH_PCROP1ASR (STM32WB_FLASH_REGS_ADDR + 0x24) #define STM32WB_FLASH_PCROP1AER (STM32WB_FLASH_REGS_ADDR + 0x28) -#define STM32WB_FLASH_WRP1AR (STM32WB_FLASH_REGS_ADDR + 0x2C) -#define STM32WB_FLASH_WRP1BR (STM32WB_FLASH_REGS_ADDR + 0x30) +#define STM32WB_FLASH_WRP1AR (STM32WB_FLASH_REGS_ADDR + 0x2C) +#define STM32WB_FLASH_WRP1BR (STM32WB_FLASH_REGS_ADDR + 0x30) #define STM32WB_FLASH_PCROP1BSR (STM32WB_FLASH_REGS_ADDR + 0x34) #define STM32WB_FLASH_PCROP1BER (STM32WB_FLASH_REGS_ADDR + 0x38) -#define STM32WB_FLASH_IPCCBR (STM32WB_FLASH_REGS_ADDR + 0x3C) -#define STM32WB_FLASH_C2ACR (STM32WB_FLASH_REGS_ADDR + 0x5C) -#define STM32WB_FLASH_C2SR (STM32WB_FLASH_REGS_ADDR + 0x60) -#define STM32WB_FLASH_C2CR (STM32WB_FLASH_REGS_ADDR + 0x64) -#define STM32WB_FLASH_SFR (STM32WB_FLASH_REGS_ADDR + 0x80) -#define STM32WB_FLASH_SRRVR (STM32WB_FLASH_REGS_ADDR + 0x84) +#define STM32WB_FLASH_IPCCBR (STM32WB_FLASH_REGS_ADDR + 0x3C) +#define STM32WB_FLASH_C2ACR (STM32WB_FLASH_REGS_ADDR + 0x5C) +#define STM32WB_FLASH_C2SR (STM32WB_FLASH_REGS_ADDR + 0x60) +#define STM32WB_FLASH_C2CR (STM32WB_FLASH_REGS_ADDR + 0x64) +#define STM32WB_FLASH_SFR (STM32WB_FLASH_REGS_ADDR + 0x80) +#define STM32WB_FLASH_SRRVR (STM32WB_FLASH_REGS_ADDR + 0x84) // WB Flash control register. -#define STM32WB_FLASH_CR_STRT (16) /* FLASH_CR Start */ -#define STM32WB_FLASH_CR_OPTLOCK (30) /* FLASH_CR Option Lock */ -#define STM32WB_FLASH_CR_LOCK (31) /* FLASH_CR Lock */ +#define STM32WB_FLASH_CR_STRT (16) /* Start */ +#define STM32WB_FLASH_CR_OPTLOCK (30) /* Option Lock */ +#define STM32WB_FLASH_CR_LOCK (31) /* Lock */ // WB Flash status register. -#define STM32WB_FLASH_SR_BSY (16) /* FLASH_SR Busy */ +#define STM32WB_FLASH_SR_ERROR_MASK (0x3f8) /* SR [9:3] */ +#define STM32WB_FLASH_SR_PROGERR (3) /* Programming alignment error */ +#define STM32WB_FLASH_SR_WRPERR (4) /* Write protection error */ +#define STM32WB_FLASH_SR_PGAERR (5) /* Programming error */ +#define STM32WB_FLASH_SR_BSY (16) /* Busy */ // 32L4 register base is at FLASH_REGS_ADDR (0x40022000) -#define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08) -#define STM32L4_FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x0C) -#define STM32L4_FLASH_SR (FLASH_REGS_ADDR + 0x10) -#define STM32L4_FLASH_CR (FLASH_REGS_ADDR + 0x14) -#define STM32L4_FLASH_OPTR (FLASH_REGS_ADDR + 0x20) - -#define STM32L4_FLASH_SR_BSY 16 -#define STM32L4_FLASH_SR_ERRMASK 0x3f8 /* SR [9:3] */ - -#define STM32L4_FLASH_CR_LOCK 31 /* Lock control register */ -#define STM32L4_FLASH_CR_OPTLOCK 30 /* Lock option bytes */ -#define STM32L4_FLASH_CR_PG 0 /* Program */ -#define STM32L4_FLASH_CR_PER 1 /* Page erase */ -#define STM32L4_FLASH_CR_MER1 2 /* Bank 1 erase */ -#define STM32L4_FLASH_CR_MER2 15 /* Bank 2 erase */ -#define STM32L4_FLASH_CR_STRT 16 /* Start command */ -#define STM32L4_FLASH_CR_OPTSTRT 17 /* Start writing option bytes */ -#define STM32L4_FLASH_CR_BKER 11 /* Bank select for page erase */ -#define STM32L4_FLASH_CR_PNB 3 /* Page number (8 bits) */ +#define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08) +#define STM32L4_FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x0C) +#define STM32L4_FLASH_SR (FLASH_REGS_ADDR + 0x10) +#define STM32L4_FLASH_CR (FLASH_REGS_ADDR + 0x14) +#define STM32L4_FLASH_OPTR (FLASH_REGS_ADDR + 0x20) + +#define STM32L4_FLASH_SR_ERROR_MASK 0x3f8 /* SR [9:3] */ +#define STM32L4_FLASH_SR_PROGERR 3 +#define STM32L4_FLASH_SR_WRPERR 4 +#define STM32L4_FLASH_SR_PGAERR 5 +#define STM32L4_FLASH_SR_BSY 16 + +#define STM32L4_FLASH_CR_LOCK 31 /* Lock control register */ +#define STM32L4_FLASH_CR_OPTLOCK 30 /* Lock option bytes */ +#define STM32L4_FLASH_CR_PG 0 /* Program */ +#define STM32L4_FLASH_CR_PER 1 /* Page erase */ +#define STM32L4_FLASH_CR_MER1 2 /* Bank 1 erase */ +#define STM32L4_FLASH_CR_MER2 15 /* Bank 2 erase */ +#define STM32L4_FLASH_CR_STRT 16 /* Start command */ +#define STM32L4_FLASH_CR_OPTSTRT 17 /* Start writing option bytes */ +#define STM32L4_FLASH_CR_BKER 11 /* Bank select for page erase */ +#define STM32L4_FLASH_CR_PNB 3 /* Page number (8 bits) */ #define STM32L4_FLASH_CR_OBL_LAUNCH 27 /* Option bytes reload */ // Bits requesting flash operations (useful when we want to clear them) -#define STM32L4_FLASH_CR_OPBITS \ - (uint32_t)((1lu << STM32L4_FLASH_CR_PG) | \ - (1lu << STM32L4_FLASH_CR_PER) | \ - (1lu << STM32L4_FLASH_CR_MER1) | \ - (1lu << STM32L4_FLASH_CR_MER1)) +#define STM32L4_FLASH_CR_OPBITS \ + (uint32_t)((1lu << STM32L4_FLASH_CR_PG) | (1lu << STM32L4_FLASH_CR_PER) | \ + (1lu << STM32L4_FLASH_CR_MER1) | (1lu << STM32L4_FLASH_CR_MER1)) // Page is fully specified by BKER and PNB #define STM32L4_FLASH_CR_PAGEMASK (uint32_t)(0x1fflu << STM32L4_FLASH_CR_PNB) -#define STM32L4_FLASH_OPTR_DUALBANK 21 +#define STM32L4_FLASH_OPTR_DUALBANK 21 // STM32L0x flash register base and offsets RM0090 - DM00031020.pdf #define STM32L0_FLASH_REGS_ADDR ((uint32_t)0x40022000) @@ -234,19 +245,22 @@ #define STM32L0_FLASH_OPTLOCK (2) #define STM32L0_FLASH_OBL_LAUNCH (18) -#define STM32L0_FLASH_SR_ERROR_MASK 0x00003F00 - -#define FLASH_ACR_OFF ((uint32_t) 0x00) -#define FLASH_PECR_OFF ((uint32_t) 0x04) -#define FLASH_PDKEYR_OFF ((uint32_t) 0x08) -#define FLASH_PEKEYR_OFF ((uint32_t) 0x0c) -#define FLASH_PRGKEYR_OFF ((uint32_t) 0x10) -#define FLASH_OPTKEYR_OFF ((uint32_t) 0x14) -#define FLASH_SR_OFF ((uint32_t) 0x18) -#define FLASH_OBR_OFF ((uint32_t) 0x1c) -#define FLASH_WRPR_OFF ((uint32_t) 0x20) - -//STM32F7 +#define STM32L0_FLASH_SR_ERROR_MASK 0x00013F00 +#define STM32L0_FLASH_SR_WRPERR 8 +#define STM32L0_FLASH_SR_PGAERR 9 +#define STM32L0_FLASH_SR_NOTZEROERR 16 + +#define FLASH_ACR_OFF ((uint32_t)0x00) +#define FLASH_PECR_OFF ((uint32_t)0x04) +#define FLASH_PDKEYR_OFF ((uint32_t)0x08) +#define FLASH_PEKEYR_OFF ((uint32_t)0x0c) +#define FLASH_PRGKEYR_OFF ((uint32_t)0x10) +#define FLASH_OPTKEYR_OFF ((uint32_t)0x14) +#define FLASH_SR_OFF ((uint32_t)0x18) +#define FLASH_OBR_OFF ((uint32_t)0x1c) +#define FLASH_WRPR_OFF ((uint32_t)0x20) + +// STM32F7 #define FLASH_F7_REGS_ADDR ((uint32_t)0x40023c00) #define FLASH_F7_KEYR (FLASH_F7_REGS_ADDR + 0x04) #define FLASH_F7_OPT_KEYR (FLASH_F7_REGS_ADDR + 0x08) @@ -266,14 +280,17 @@ #define FLASH_F7_SR_PGP_ERR 6 /* Programming parallelism error */ #define FLASH_F7_SR_PGA_ERR 5 /* Programming alignment error */ #define FLASH_F7_SR_WRP_ERR 4 /* Write protection error */ -#define FLASH_F7_SR_OP_ERR 1 /* Operation error */ -#define FLASH_F7_SR_EOP 0 /* End of operation */ +#define FLASH_F7_SR_OP_ERR 1 /* Operation error */ +#define FLASH_F7_SR_EOP 0 /* End of operation */ #define FLASH_F7_OPTCR1_BOOT_ADD0 0 #define FLASH_F7_OPTCR1_BOOT_ADD1 16 -#define FLASH_F7_SR_ERROR_MASK ((1 << FLASH_F7_SR_ERS_ERR) | (1 << FLASH_F7_SR_PGP_ERR) | (1 << FLASH_F7_SR_PGA_ERR) | (1 << FLASH_F7_SR_WRP_ERR) | (1 << FLASH_F7_SR_OP_ERR)) +#define FLASH_F7_SR_ERROR_MASK \ + ((1 << FLASH_F7_SR_ERS_ERR) | (1 << FLASH_F7_SR_PGP_ERR) | \ + (1 << FLASH_F7_SR_PGA_ERR) | (1 << FLASH_F7_SR_WRP_ERR) | \ + (1 << FLASH_F7_SR_OP_ERR)) -//STM32F4 +// STM32F4 #define FLASH_F4_REGS_ADDR ((uint32_t)0x40023c00) #define FLASH_F4_KEYR (FLASH_F4_REGS_ADDR + 0x04) #define FLASH_F4_OPT_KEYR (FLASH_F4_REGS_ADDR + 0x08) @@ -287,6 +304,9 @@ #define FLASH_F4_CR_SER 1 #define FLASH_F4_CR_SNB 3 #define FLASH_F4_CR_SNB_MASK 0xf8 +#define FLASH_F4_SR_ERROR_MASK 0x000000F0 +#define FLASH_F4_SR_PGAERR 5 +#define FLASH_F4_SR_WRPERR 4 #define FLASH_F4_SR_BSY 16 // STM32F2 @@ -311,15 +331,17 @@ #define FLASH_H7_CR_SER 2 #define FLASH_H7_CR_BER 3 #define FLASH_H7_CR_PSIZE 4 -#define FLASH_H7_CR_START(chipid) (chipid==STLINK_CHIPID_STM32_H7AX?5:7) +#define FLASH_H7_CR_START(chipid) (chipid == STLINK_CHIPID_STM32_H7AX ? 5 : 7) #define FLASH_H7_CR_SNB 8 #define FLASH_H7_CR_SNB_MASK 0x700 -#define FLASH_H7_SR_QW 2 +#define FLASH_H7_SR_QW 2 #define FLASH_H7_SR_WRPERR 17 #define FLASH_H7_SR_PGSERR 18 #define FLASH_H7_SR_STRBERR 19 -#define FLASH_H7_SR_ERROR_MASK ((1 << FLASH_H7_SR_PGSERR) | (1 << FLASH_H7_SR_STRBERR) | (1 << FLASH_H7_SR_WRPERR)) +#define FLASH_H7_SR_ERROR_MASK \ + ((1 << FLASH_H7_SR_PGSERR) | (1 << FLASH_H7_SR_STRBERR) | \ + (1 << FLASH_H7_SR_WRPERR)) #define FLASH_H7_OPTCR_OPTLOCK 0 #define FLASH_H7_OPTCR_OPTSTART 1 @@ -346,927 +368,1211 @@ #define FLASH_H7_OPTSR_CUR (FLASH_H7_REGS_ADDR + 0x1c) #define FLASH_H7_OPTCCR (FLASH_H7_REGS_ADDR + 0x24) +#define STM32F0_DBGMCU_CR 0xE0042004 +#define STM32F0_DBGMCU_CR_IWDG_STOP 8 +#define STM32F0_DBGMCU_CR_WWDG_STOP 9 + +#define STM32F4_DBGMCU_APB1FZR1 0xE0042008 +#define STM32F4_DBGMCU_APB1FZR1_WWDG_STOP 11 +#define STM32F4_DBGMCU_APB1FZR1_IWDG_STOP 12 + +#define STM32L0_DBGMCU_APB1_FZ 0x40015808 +#define STM32L0_DBGMCU_APB1_FZ_WWDG_STOP 11 +#define STM32L0_DBGMCU_APB1_FZ_IWDG_STOP 12 + +#define STM32H7_DBGMCU_APB1HFZ 0x5C001054 +#define STM32H7_DBGMCU_APB1HFZ_IWDG_STOP 18 + +#define STM32WB_DBGMCU_APB1FZR1 0xE004203C +#define STM32WB_DBGMCU_APB1FZR1_WWDG_STOP 11 +#define STM32WB_DBGMCU_APB1FZR1_IWDG_STOP 12 + +#define STM32F1_RCC_AHBENR 0x40021014 +#define STM32F1_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN + +#define STM32F4_RCC_AHB1ENR 0x40023830 +#define STM32F4_RCC_DMAEN 0x00600000 // DMA2EN | DMA1EN + +#define STM32G0_RCC_AHBENR 0x40021038 +#define STM32G0_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN + +#define STM32G4_RCC_AHB1ENR 0x40021048 +#define STM32G4_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN + +#define STM32L0_RCC_AHBENR 0x40021030 +#define STM32L0_RCC_DMAEN 0x00000001 // DMAEN + +#define STM32H7_RCC_AHB1ENR 0x58024538 +#define STM32H7_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN + +#define STM32WB_RCC_AHB1ENR 0x58000048 +#define STM32WB_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN + #define L1_WRITE_BLOCK_SIZE 0x80 #define L0_WRITE_BLOCK_SIZE 0x40 - // Endianness // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html // These functions encode and decode little endian uint16 and uint32 values. -void write_uint32(unsigned char* buf, uint32_t ui) { - buf[0] = ui; - buf[1] = ui >> 8; - buf[2] = ui >> 16; - buf[3] = ui >> 24; +void write_uint32(unsigned char *buf, uint32_t ui) { + buf[0] = ui; + buf[1] = ui >> 8; + buf[2] = ui >> 16; + buf[3] = ui >> 24; } -void write_uint16(unsigned char* buf, uint16_t ui) { - buf[0] = ui ; - buf[1] = ui >> 8; +void write_uint16(unsigned char *buf, uint16_t ui) { + buf[0] = ui; + buf[1] = ui >> 8; } uint32_t read_uint32(const unsigned char *c, const int pt) { - return ((uint32_t)c[pt]) | ((uint32_t)c[pt+1] << 8) | ((uint32_t)c[pt+2] << 16) | ((uint32_t)c[pt+3] << 24) ; + return ((uint32_t)c[pt]) | ((uint32_t)c[pt + 1] << 8) | + ((uint32_t)c[pt + 2] << 16) | ((uint32_t)c[pt + 3] << 24); } uint16_t read_uint16(const unsigned char *c, const int pt) { - return ((uint16_t)c[pt]) | ((uint16_t)c[pt+1] << 8); + return ((uint16_t)c[pt]) | ((uint16_t)c[pt + 1] << 8); } +static uint32_t get_stm32l0_flash_base(stlink_t *sl) { + switch (sl->chip_id) { + case STLINK_CHIPID_STM32_L0: + case STLINK_CHIPID_STM32_L0_CAT5: + case STLINK_CHIPID_STM32_L0_CAT2: + case STLINK_CHIPID_STM32_L011: + return (STM32L0_FLASH_REGS_ADDR); -static uint32_t get_stm32l0_flash_base(stlink_t *sl) -{ - switch (sl->chip_id) { - case STLINK_CHIPID_STM32_L1_CAT2: - case STLINK_CHIPID_STM32_L1_MEDIUM: - case STLINK_CHIPID_STM32_L1_MEDIUM_PLUS: - case STLINK_CHIPID_STM32_L1_HIGH: - return(STM32L1_FLASH_REGS_ADDR); - default: - return(STM32L0_FLASH_REGS_ADDR); - } + case STLINK_CHIPID_STM32_L1_CAT2: + case STLINK_CHIPID_STM32_L1_MEDIUM: + case STLINK_CHIPID_STM32_L1_MEDIUM_PLUS: + case STLINK_CHIPID_STM32_L1_HIGH: + return (STM32L1_FLASH_REGS_ADDR); + + default: + WLOG("Flash base use default L0 address"); + return (STM32L0_FLASH_REGS_ADDR); + } } static uint32_t __attribute__((unused)) read_flash_rdp(stlink_t *sl) { - uint32_t rdp; - stlink_read_debug32(sl, FLASH_WRPR, &rdp); - return(rdp & 0xff); + uint32_t rdp; + stlink_read_debug32(sl, FLASH_WRPR, &rdp); + return (rdp & 0xff); } static inline uint32_t read_flash_cr(stlink_t *sl, unsigned bank) { - uint32_t reg, res; - - if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - reg = FLASH_F4_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - reg = FLASH_F7_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - reg = STM32L4_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - reg = STM32Gx_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - reg = STM32WB_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - reg = (bank == BANK_1)?FLASH_H7_CR1:FLASH_H7_CR2; - } else { - reg = (bank == BANK_1)?FLASH_CR:FLASH_CR2; - } - - stlink_read_debug32(sl, reg, &res); + uint32_t reg, res; + + if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + reg = FLASH_F4_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + reg = FLASH_F7_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + reg = STM32L4_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + reg = STM32Gx_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + reg = STM32WB_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2; + } else { + reg = (bank == BANK_1) ? FLASH_CR : FLASH_CR2; + } + + stlink_read_debug32(sl, reg, &res); #if DEBUG_FLASH - fprintf(stdout, "CR:0x%x\n", res); + fprintf(stdout, "CR:0x%x\n", res); #endif - return(res); + return (res); } static inline unsigned int is_flash_locked(stlink_t *sl) { - /* return non zero for true */ - uint32_t cr_lock_shift; - uint32_t cr_reg; - uint32_t n; - - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { - cr_reg = FLASH_CR; - cr_lock_shift = FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - cr_reg = FLASH_F4_CR; - cr_lock_shift = FLASH_F4_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - cr_reg = FLASH_F7_CR; - cr_lock_shift = FLASH_F7_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - cr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; - cr_lock_shift = STM32L0_FLASH_PELOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - cr_reg = STM32L4_FLASH_CR; - cr_lock_shift = STM32L4_FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - cr_lock_shift = STM32Gx_FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - cr_lock_shift = STM32WB_FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = FLASH_H7_CR1; - cr_lock_shift = FLASH_H7_CR_LOCK; - } else { - ELOG("unsupported flash method, abort\n"); - return(-1); - } - - stlink_read_debug32(sl, cr_reg, &n); - return(n & (1u << cr_lock_shift)); + /* return non zero for true */ + uint32_t cr_lock_shift; + uint32_t cr_reg; + uint32_t n; + + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + cr_reg = FLASH_CR; + cr_lock_shift = FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + cr_reg = FLASH_F4_CR; + cr_lock_shift = FLASH_F4_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + cr_reg = FLASH_F7_CR; + cr_lock_shift = FLASH_F7_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + cr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; + cr_lock_shift = STM32L0_FLASH_PELOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + cr_reg = STM32L4_FLASH_CR; + cr_lock_shift = STM32L4_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + cr_lock_shift = STM32Gx_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + cr_lock_shift = STM32WB_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = FLASH_H7_CR1; + cr_lock_shift = FLASH_H7_CR_LOCK; + } else { + ELOG("unsupported flash method, abort\n"); + return (-1); + } + + stlink_read_debug32(sl, cr_reg, &n); + return (n & (1u << cr_lock_shift)); } static void unlock_flash(stlink_t *sl) { - uint32_t key_reg, key2_reg = 0; - uint32_t flash_key1 = FLASH_KEY1; - uint32_t flash_key2 = FLASH_KEY2; - /* The unlock sequence consists of 2 write cycles where 2 key values are written - * to the FLASH_KEYR register. - * An invalid sequence results in a definitive lock of the FPEC block until next reset. - */ - - if (sl->flash_type == STLINK_FLASH_TYPE_F0) { - key_reg = FLASH_KEYR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { - key_reg = FLASH_KEYR; - key2_reg = FLASH_KEYR2; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - key_reg = FLASH_F4_KEYR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - key_reg = FLASH_F7_KEYR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - key_reg = get_stm32l0_flash_base(sl) + FLASH_PEKEYR_OFF; - flash_key1 = FLASH_L0_PEKEY1; - flash_key2 = FLASH_L0_PEKEY2; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - key_reg = STM32L4_FLASH_KEYR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - key_reg = STM32Gx_FLASH_KEYR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - key_reg = STM32WB_FLASH_KEYR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - key_reg = FLASH_H7_KEYR1; - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - key2_reg = FLASH_H7_KEYR2; - } - } else { - ELOG("unsupported flash method, abort\n"); - return; - } + uint32_t key_reg, key2_reg = 0; + uint32_t flash_key1 = FLASH_KEY1; + uint32_t flash_key2 = FLASH_KEY2; + /* The unlock sequence consists of 2 write cycles where 2 key values are + * written to the FLASH_KEYR register. An invalid sequence results in a + * definitive lock of the FPEC block until next reset. + */ + + if (sl->flash_type == STLINK_FLASH_TYPE_F0) { + key_reg = FLASH_KEYR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + key_reg = FLASH_KEYR; + key2_reg = FLASH_KEYR2; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + key_reg = FLASH_F4_KEYR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + key_reg = FLASH_F7_KEYR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + key_reg = get_stm32l0_flash_base(sl) + FLASH_PEKEYR_OFF; + flash_key1 = FLASH_L0_PEKEY1; + flash_key2 = FLASH_L0_PEKEY2; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + key_reg = STM32L4_FLASH_KEYR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + key_reg = STM32Gx_FLASH_KEYR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + key_reg = STM32WB_FLASH_KEYR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + key_reg = FLASH_H7_KEYR1; + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + key2_reg = FLASH_H7_KEYR2; + } + } else { + ELOG("unsupported flash method, abort\n"); + return; + } - stlink_write_debug32(sl, key_reg, flash_key1); - stlink_write_debug32(sl, key_reg, flash_key2); + stlink_write_debug32(sl, key_reg, flash_key1); + stlink_write_debug32(sl, key_reg, flash_key2); - if (key2_reg) { - stlink_write_debug32(sl, key2_reg, flash_key1); - stlink_write_debug32(sl, key2_reg, flash_key2); - } + if (key2_reg) { + stlink_write_debug32(sl, key2_reg, flash_key1); + stlink_write_debug32(sl, key2_reg, flash_key2); + } } /* unlock flash if already locked */ static int unlock_flash_if(stlink_t *sl) { - if (is_flash_locked(sl)) { - unlock_flash(sl); + if (is_flash_locked(sl)) { + unlock_flash(sl); - if (is_flash_locked(sl)) { - WLOG("Failed to unlock flash!\n"); - return(-1); - } + if (is_flash_locked(sl)) { + WLOG("Failed to unlock flash!\n"); + return (-1); } + } - DLOG("Successfully unlocked flash\n"); - return(0); + DLOG("Successfully unlocked flash\n"); + return (0); } static void lock_flash(stlink_t *sl) { - uint32_t cr_lock_shift, cr_reg, n, cr2_reg = 0; - uint32_t cr_mask = 0xffffffffu; - - if (sl->flash_type == STLINK_FLASH_TYPE_F0) { - cr_reg = FLASH_CR; - cr_lock_shift = FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { - cr_reg = FLASH_CR; - cr2_reg = FLASH_CR2; - cr_lock_shift = FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - cr_reg = FLASH_F4_CR; - cr_lock_shift = FLASH_F4_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - cr_reg = FLASH_F7_CR; - cr_lock_shift = FLASH_F7_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - cr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; - cr_lock_shift = STM32L0_FLASH_PELOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - cr_reg = STM32L4_FLASH_CR; - cr_lock_shift = STM32L4_FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - cr_lock_shift = STM32Gx_FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - cr_lock_shift = STM32WB_FLASH_CR_LOCK; - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = FLASH_H7_CR1; - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - cr2_reg = FLASH_H7_CR2; - } - cr_lock_shift = FLASH_H7_CR_LOCK; - cr_mask = ~(1u << FLASH_H7_CR_SER); - } else { - ELOG("unsupported flash method, abort\n"); - return; - } + uint32_t cr_lock_shift, cr_reg, n, cr2_reg = 0; + uint32_t cr_mask = 0xffffffffu; + + if (sl->flash_type == STLINK_FLASH_TYPE_F0) { + cr_reg = FLASH_CR; + cr_lock_shift = FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + cr_reg = FLASH_CR; + cr2_reg = FLASH_CR2; + cr_lock_shift = FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + cr_reg = FLASH_F4_CR; + cr_lock_shift = FLASH_F4_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + cr_reg = FLASH_F7_CR; + cr_lock_shift = FLASH_F7_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + cr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; + cr_lock_shift = STM32L0_FLASH_PELOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + cr_reg = STM32L4_FLASH_CR; + cr_lock_shift = STM32L4_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + cr_lock_shift = STM32Gx_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + cr_lock_shift = STM32WB_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = FLASH_H7_CR1; + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + cr2_reg = FLASH_H7_CR2; + } + cr_lock_shift = FLASH_H7_CR_LOCK; + cr_mask = ~(1u << FLASH_H7_CR_SER); + } else { + ELOG("unsupported flash method, abort\n"); + return; + } - stlink_read_debug32(sl, cr_reg, &n); - n &= cr_mask; - n |= (1u << cr_lock_shift); - stlink_write_debug32(sl, cr_reg, n); + stlink_read_debug32(sl, cr_reg, &n); + n &= cr_mask; + n |= (1u << cr_lock_shift); + stlink_write_debug32(sl, cr_reg, n); - if (cr2_reg) { - n = read_flash_cr(sl, BANK_2) | (1u << cr_lock_shift); - stlink_write_debug32(sl, cr2_reg, n); - } + if (cr2_reg) { + n = read_flash_cr(sl, BANK_2) | (1u << cr_lock_shift); + stlink_write_debug32(sl, cr2_reg, n); + } } static bool is_flash_option_locked(stlink_t *sl) { - uint32_t optlock_shift, optcr_reg; - int active_bit_level = 1; - uint32_t n; - - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - case STLINK_FLASH_TYPE_F1_XL: - optcr_reg = FLASH_CR; - optlock_shift = FLASH_CR_OPTWRE; - active_bit_level = 0; /* bit is "option write enable", not lock */ - break; - case STLINK_FLASH_TYPE_F4: - optcr_reg = FLASH_F4_OPTCR; - optlock_shift = FLASH_F4_OPTCR_LOCK; - break; - case STLINK_FLASH_TYPE_F7: - optcr_reg = FLASH_F7_OPTCR; - optlock_shift = FLASH_F7_OPTCR_LOCK; - break; - case STLINK_FLASH_TYPE_L0: - optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; - optlock_shift = STM32L0_FLASH_OPTLOCK; - break; - case STLINK_FLASH_TYPE_L4: - optcr_reg = STM32L4_FLASH_CR; - optlock_shift = STM32L4_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - optcr_reg = STM32Gx_FLASH_CR; - optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_WB: - optcr_reg = STM32WB_FLASH_CR; - optlock_shift = STM32WB_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_H7: - optcr_reg = FLASH_H7_OPTCR; - optlock_shift = FLASH_H7_OPTCR_OPTLOCK; - break; - default: - ELOG("unsupported flash method, abort\n"); - return -1; - } - - stlink_read_debug32(sl, optcr_reg, &n); - - if (active_bit_level == 0) { - return(!(n & (1u << optlock_shift))); - } - - return(n & (1u << optlock_shift)); - + uint32_t optlock_shift, optcr_reg; + int active_bit_level = 1; + uint32_t n; + + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + optcr_reg = FLASH_CR; + optlock_shift = FLASH_CR_OPTWRE; + active_bit_level = 0; /* bit is "option write enable", not lock */ + break; + case STLINK_FLASH_TYPE_F4: + optcr_reg = FLASH_F4_OPTCR; + optlock_shift = FLASH_F4_OPTCR_LOCK; + break; + case STLINK_FLASH_TYPE_F7: + optcr_reg = FLASH_F7_OPTCR; + optlock_shift = FLASH_F7_OPTCR_LOCK; + break; + case STLINK_FLASH_TYPE_L0: + optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; + optlock_shift = STM32L0_FLASH_OPTLOCK; + break; + case STLINK_FLASH_TYPE_L4: + optcr_reg = STM32L4_FLASH_CR; + optlock_shift = STM32L4_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + optcr_reg = STM32Gx_FLASH_CR; + optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_WB: + optcr_reg = STM32WB_FLASH_CR; + optlock_shift = STM32WB_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_H7: + optcr_reg = FLASH_H7_OPTCR; + optlock_shift = FLASH_H7_OPTCR_OPTLOCK; + break; + default: + ELOG("unsupported flash method, abort\n"); + return -1; + } + + stlink_read_debug32(sl, optcr_reg, &n); + + if (active_bit_level == 0) { + return (!(n & (1u << optlock_shift))); + } + + return (n & (1u << optlock_shift)); } static int lock_flash_option(stlink_t *sl) { - uint32_t optlock_shift, optcr_reg, n, optcr2_reg = 0; - int active_bit_level = 1; - - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - case STLINK_FLASH_TYPE_F1_XL: - optcr_reg = FLASH_CR; - optlock_shift = FLASH_CR_OPTWRE; - active_bit_level = 0; - break; - case STLINK_FLASH_TYPE_F4: - optcr_reg = FLASH_F4_OPTCR; - optlock_shift = FLASH_F4_OPTCR_LOCK; - break; - case STLINK_FLASH_TYPE_F7: - optcr_reg = FLASH_F7_OPTCR; - optlock_shift = FLASH_F7_OPTCR_LOCK; - break; - case STLINK_FLASH_TYPE_L0: - optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; - optlock_shift = STM32L0_FLASH_OPTLOCK; - break; - case STLINK_FLASH_TYPE_L4: - optcr_reg = STM32L4_FLASH_CR; - optlock_shift = STM32L4_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - optcr_reg = STM32Gx_FLASH_CR; - optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_WB: - optcr_reg = STM32WB_FLASH_CR; - optlock_shift = STM32WB_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_H7: - optcr_reg = FLASH_H7_OPTCR; - optlock_shift = FLASH_H7_OPTCR_OPTLOCK; - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) - optcr2_reg = FLASH_H7_OPTCR2; - break; - default: - ELOG("unsupported flash method, abort\n"); - return -1; - } - - stlink_read_debug32(sl, optcr_reg, &n); + uint32_t optlock_shift, optcr_reg, n, optcr2_reg = 0; + int active_bit_level = 1; + + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + optcr_reg = FLASH_CR; + optlock_shift = FLASH_CR_OPTWRE; + active_bit_level = 0; + break; + case STLINK_FLASH_TYPE_F4: + optcr_reg = FLASH_F4_OPTCR; + optlock_shift = FLASH_F4_OPTCR_LOCK; + break; + case STLINK_FLASH_TYPE_F7: + optcr_reg = FLASH_F7_OPTCR; + optlock_shift = FLASH_F7_OPTCR_LOCK; + break; + case STLINK_FLASH_TYPE_L0: + optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; + optlock_shift = STM32L0_FLASH_OPTLOCK; + break; + case STLINK_FLASH_TYPE_L4: + optcr_reg = STM32L4_FLASH_CR; + optlock_shift = STM32L4_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + optcr_reg = STM32Gx_FLASH_CR; + optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_WB: + optcr_reg = STM32WB_FLASH_CR; + optlock_shift = STM32WB_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_H7: + optcr_reg = FLASH_H7_OPTCR; + optlock_shift = FLASH_H7_OPTCR_OPTLOCK; + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) + optcr2_reg = FLASH_H7_OPTCR2; + break; + default: + ELOG("unsupported flash method, abort\n"); + return -1; + } + + stlink_read_debug32(sl, optcr_reg, &n); + + if (active_bit_level == 0) { + n &= ~(1u << optlock_shift); + } else { + n |= (1u << optlock_shift); + } + + stlink_write_debug32(sl, optcr_reg, n); + + if (optcr2_reg) { + stlink_read_debug32(sl, optcr2_reg, &n); if (active_bit_level == 0) { - n &= ~(1u << optlock_shift); + n &= ~(1u << optlock_shift); } else { - n |= (1u << optlock_shift); + n |= (1u << optlock_shift); } - stlink_write_debug32(sl, optcr_reg, n); - - if (optcr2_reg) { - stlink_read_debug32(sl, optcr2_reg, &n); - - if (active_bit_level == 0) { - n &= ~(1u << optlock_shift); - } else { - n |= (1u << optlock_shift); - } - - stlink_write_debug32(sl, optcr2_reg, n); - } + stlink_write_debug32(sl, optcr2_reg, n); + } - return(0); + return (0); } static int unlock_flash_option(stlink_t *sl) { - uint32_t optkey_reg, optkey2_reg = 0; - uint32_t optkey1 = FLASH_OPTKEY1; - uint32_t optkey2 = FLASH_OPTKEY2; - - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - case STLINK_FLASH_TYPE_F1_XL: - optkey_reg = FLASH_OPTKEYR; - optkey1 = FLASH_F0_OPTKEY1; - optkey2 = FLASH_F0_OPTKEY2; - break; - case STLINK_FLASH_TYPE_F4: - optkey_reg = FLASH_F4_OPT_KEYR; - break; - case STLINK_FLASH_TYPE_F7: - optkey_reg = FLASH_F7_OPT_KEYR; - break; - case STLINK_FLASH_TYPE_L0: - optkey_reg = get_stm32l0_flash_base(sl) + FLASH_OPTKEYR_OFF; - optkey1 = FLASH_L0_OPTKEY1; - optkey2 = FLASH_L0_OPTKEY2; - break; - case STLINK_FLASH_TYPE_L4: - optkey_reg = STM32L4_FLASH_OPTKEYR; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - optkey_reg = STM32Gx_FLASH_OPTKEYR; - break; - case STLINK_FLASH_TYPE_WB: - optkey_reg = STM32WB_FLASH_OPT_KEYR; - break; - case STLINK_FLASH_TYPE_H7: - optkey_reg = FLASH_H7_OPT_KEYR; - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) - optkey2_reg = FLASH_H7_OPT_KEYR2; - break; - default: - ELOG("unsupported flash method, abort\n"); - return(-1); - } - - stlink_write_debug32(sl, optkey_reg, optkey1); - stlink_write_debug32(sl, optkey_reg, optkey2); - - if (optkey2_reg) { - stlink_write_debug32(sl, optkey2_reg, optkey1); - stlink_write_debug32(sl, optkey2_reg, optkey2); - } - - return(0); + uint32_t optkey_reg, optkey2_reg = 0; + uint32_t optkey1 = FLASH_OPTKEY1; + uint32_t optkey2 = FLASH_OPTKEY2; + + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + optkey_reg = FLASH_OPTKEYR; + optkey1 = FLASH_F0_OPTKEY1; + optkey2 = FLASH_F0_OPTKEY2; + break; + case STLINK_FLASH_TYPE_F4: + optkey_reg = FLASH_F4_OPT_KEYR; + break; + case STLINK_FLASH_TYPE_F7: + optkey_reg = FLASH_F7_OPT_KEYR; + break; + case STLINK_FLASH_TYPE_L0: + optkey_reg = get_stm32l0_flash_base(sl) + FLASH_OPTKEYR_OFF; + optkey1 = FLASH_L0_OPTKEY1; + optkey2 = FLASH_L0_OPTKEY2; + break; + case STLINK_FLASH_TYPE_L4: + optkey_reg = STM32L4_FLASH_OPTKEYR; + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + optkey_reg = STM32Gx_FLASH_OPTKEYR; + break; + case STLINK_FLASH_TYPE_WB: + optkey_reg = STM32WB_FLASH_OPT_KEYR; + break; + case STLINK_FLASH_TYPE_H7: + optkey_reg = FLASH_H7_OPT_KEYR; + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) + optkey2_reg = FLASH_H7_OPT_KEYR2; + break; + default: + ELOG("unsupported flash method, abort\n"); + return (-1); + } + + stlink_write_debug32(sl, optkey_reg, optkey1); + stlink_write_debug32(sl, optkey_reg, optkey2); + + if (optkey2_reg) { + stlink_write_debug32(sl, optkey2_reg, optkey1); + stlink_write_debug32(sl, optkey2_reg, optkey2); + } + + return (0); } static int unlock_flash_option_if(stlink_t *sl) { - if (is_flash_option_locked(sl)) { - if (unlock_flash_option(sl)) { - ELOG("Could not unlock flash option!\n"); - return(-1); - } + if (is_flash_option_locked(sl)) { + if (unlock_flash_option(sl)) { + ELOG("Could not unlock flash option!\n"); + return (-1); + } - if (is_flash_option_locked(sl)) { - ELOG("Failed to unlock flash option!\n"); - return(-1); - } + if (is_flash_option_locked(sl)) { + ELOG("Failed to unlock flash option!\n"); + return (-1); } + } - DLOG("Successfully unlocked flash option\n"); - return(0); + DLOG("Successfully unlocked flash option\n"); + return (0); } static void set_flash_cr_pg(stlink_t *sl, unsigned bank) { - uint32_t cr_reg, x; - - x = read_flash_cr(sl, bank); - - if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - cr_reg = FLASH_F4_CR; - x |= 1 << FLASH_CR_PG; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - cr_reg = FLASH_F7_CR; - x |= 1 << FLASH_CR_PG; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - cr_reg = STM32L4_FLASH_CR; - x &= ~STM32L4_FLASH_CR_OPBITS; - x |= (1 << STM32L4_FLASH_CR_PG); - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - x |= (1 << FLASH_CR_PG); - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - x |= (1 << FLASH_CR_PG); - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = (bank == BANK_1)?FLASH_H7_CR1:FLASH_H7_CR2; - x |= (1 << FLASH_H7_CR_PG); - } else { - cr_reg = FLASH_CR; - x = (1 << FLASH_CR_PG); - } - - stlink_write_debug32(sl, cr_reg, x); + uint32_t cr_reg, x; + + x = read_flash_cr(sl, bank); + + if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + cr_reg = FLASH_F4_CR; + x |= 1 << FLASH_CR_PG; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + cr_reg = FLASH_F7_CR; + x |= 1 << FLASH_CR_PG; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + cr_reg = STM32L4_FLASH_CR; + x &= ~STM32L4_FLASH_CR_OPBITS; + x |= (1 << STM32L4_FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + x |= (1 << FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + x |= (1 << FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2; + x |= (1 << FLASH_H7_CR_PG); + } else { + cr_reg = FLASH_CR; + x = (1 << FLASH_CR_PG); + } + + stlink_write_debug32(sl, cr_reg, x); } static void clear_flash_cr_pg(stlink_t *sl, unsigned bank) { - uint32_t cr_reg, n; - uint32_t bit = FLASH_CR_PG; - - if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - cr_reg = FLASH_F4_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - cr_reg = FLASH_F7_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - cr_reg = STM32L4_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = (bank == BANK_1)?FLASH_H7_CR1:FLASH_H7_CR2; - bit = FLASH_H7_CR_PG; - } else { - cr_reg = FLASH_CR; - } - - n = read_flash_cr(sl, bank) & ~(1 << bit); - stlink_write_debug32(sl, cr_reg, n); + uint32_t cr_reg, n; + uint32_t bit = FLASH_CR_PG; + + if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + cr_reg = FLASH_F4_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + cr_reg = FLASH_F7_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + cr_reg = STM32L4_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2; + bit = FLASH_H7_CR_PG; + } else { + cr_reg = FLASH_CR; + } + + n = read_flash_cr(sl, bank) & ~(1 << bit); + stlink_write_debug32(sl, cr_reg, n); } static void set_flash_cr_per(stlink_t *sl, unsigned bank) { - uint32_t cr_reg, val; + uint32_t cr_reg, val; - if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - } else { - cr_reg = (bank==BANK_1)?FLASH_CR:FLASH_CR2; - } + if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + } else { + cr_reg = (bank == BANK_1) ? FLASH_CR : FLASH_CR2; + } - stlink_read_debug32(sl, cr_reg, &val); - val |= (1 << FLASH_CR_PER); - stlink_write_debug32(sl, cr_reg, val); + stlink_read_debug32(sl, cr_reg, &val); + val |= (1 << FLASH_CR_PER); + stlink_write_debug32(sl, cr_reg, val); } static void clear_flash_cr_per(stlink_t *sl, unsigned bank) { - uint32_t cr_reg; + uint32_t cr_reg; - if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - } else { - cr_reg = (bank==BANK_1)?FLASH_CR:FLASH_CR2; - } + if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + } else { + cr_reg = (bank == BANK_1) ? FLASH_CR : FLASH_CR2; + } - const uint32_t n = read_flash_cr(sl, bank) & ~(1 << FLASH_CR_PER); - stlink_write_debug32(sl, cr_reg, n); + const uint32_t n = read_flash_cr(sl, bank) & ~(1 << FLASH_CR_PER); + stlink_write_debug32(sl, cr_reg, n); } static void set_flash_cr_mer(stlink_t *sl, bool v, unsigned bank) { - uint32_t val, cr_reg, cr_mer, cr_pg; - - if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - cr_reg = FLASH_F4_CR; - cr_mer = 1 << FLASH_CR_MER; - cr_pg = 1 << FLASH_CR_PG; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - cr_reg = FLASH_F7_CR; - cr_mer = 1 << FLASH_CR_MER; - cr_pg = 1 << FLASH_CR_PG; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - cr_reg = STM32L4_FLASH_CR; - cr_mer = (1 << STM32L4_FLASH_CR_MER1) | (1 << STM32L4_FLASH_CR_MER2); - cr_pg = (1 << STM32L4_FLASH_CR_PG); - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - cr_mer = (1 << STM32Gx_FLASH_CR_MER1); - - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - cr_mer |= (1 << STM32Gx_FLASH_CR_MER2); - } - - cr_pg = (1 << FLASH_CR_PG); - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - cr_mer = (1 << FLASH_CR_MER); - cr_pg = (1 << FLASH_CR_PG); - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = (bank==BANK_1)?FLASH_H7_CR1:FLASH_H7_CR2; - cr_mer = (1 << FLASH_H7_CR_BER); - cr_pg = (1 << FLASH_H7_CR_PG); - } else { - cr_reg = (bank==BANK_1)?FLASH_CR:FLASH_CR2; - cr_mer = (1 << FLASH_CR_MER); - cr_pg = (1 << FLASH_CR_PG); - } - - stlink_read_debug32(sl, cr_reg, &val); - - if (val & cr_pg) { - // STM32F030 will drop MER bit if PG was set - val &= ~cr_pg; - stlink_write_debug32(sl, cr_reg, val); - } + uint32_t val, cr_reg, cr_mer, cr_pg; + + if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + cr_reg = FLASH_F4_CR; + cr_mer = 1 << FLASH_CR_MER; + cr_pg = 1 << FLASH_CR_PG; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + cr_reg = FLASH_F7_CR; + cr_mer = 1 << FLASH_CR_MER; + cr_pg = 1 << FLASH_CR_PG; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + cr_reg = STM32L4_FLASH_CR; + cr_mer = (1 << STM32L4_FLASH_CR_MER1) | (1 << STM32L4_FLASH_CR_MER2); + cr_pg = (1 << STM32L4_FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + cr_mer = (1 << STM32Gx_FLASH_CR_MER1); + + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + cr_mer |= (1 << STM32Gx_FLASH_CR_MER2); + } + + cr_pg = (1 << FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + cr_mer = (1 << FLASH_CR_MER); + cr_pg = (1 << FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2; + cr_mer = (1 << FLASH_H7_CR_BER); + cr_pg = (1 << FLASH_H7_CR_PG); + } else { + cr_reg = (bank == BANK_1) ? FLASH_CR : FLASH_CR2; + cr_mer = (1 << FLASH_CR_MER); + cr_pg = (1 << FLASH_CR_PG); + } + + stlink_read_debug32(sl, cr_reg, &val); + + if (val & cr_pg) { + // STM32F030 will drop MER bit if PG was set + val &= ~cr_pg; + stlink_write_debug32(sl, cr_reg, val); + } - if (v) { - val |= cr_mer; - } else { - val &= ~cr_mer; - } + if (v) { + val |= cr_mer; + } else { + val &= ~cr_mer; + } - stlink_write_debug32(sl, cr_reg, val); + stlink_write_debug32(sl, cr_reg, val); } static void set_flash_cr_strt(stlink_t *sl, unsigned bank) { - uint32_t val, cr_reg, cr_strt; - - if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - cr_reg = FLASH_F4_CR; - cr_strt = 1 << FLASH_F4_CR_STRT; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - cr_reg = FLASH_F7_CR; - cr_strt = 1 << FLASH_F7_CR_STRT; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - cr_reg = STM32L4_FLASH_CR; - cr_strt = (1 << STM32L4_FLASH_CR_STRT); - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - cr_reg = STM32Gx_FLASH_CR; - cr_strt = (1 << STM32Gx_FLASH_CR_STRT); - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - cr_reg = STM32WB_FLASH_CR; - cr_strt = (1 << STM32WB_FLASH_CR_STRT); - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = (bank==BANK_1)?FLASH_H7_CR1:FLASH_H7_CR2; - cr_strt = 1 << FLASH_H7_CR_START(sl->chip_id); - } else { - cr_reg = (bank==BANK_1)?FLASH_CR:FLASH_CR2; - cr_strt = (1 << FLASH_CR_STRT); - } - - stlink_read_debug32(sl, cr_reg, &val); - val |= cr_strt; - stlink_write_debug32(sl, cr_reg, val); + uint32_t val, cr_reg, cr_strt; + + if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + cr_reg = FLASH_F4_CR; + cr_strt = 1 << FLASH_F4_CR_STRT; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + cr_reg = FLASH_F7_CR; + cr_strt = 1 << FLASH_F7_CR_STRT; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + cr_reg = STM32L4_FLASH_CR; + cr_strt = (1 << STM32L4_FLASH_CR_STRT); + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + cr_reg = STM32Gx_FLASH_CR; + cr_strt = (1 << STM32Gx_FLASH_CR_STRT); + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + cr_reg = STM32WB_FLASH_CR; + cr_strt = (1 << STM32WB_FLASH_CR_STRT); + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2; + cr_strt = 1 << FLASH_H7_CR_START(sl->chip_id); + } else { + cr_reg = (bank == BANK_1) ? FLASH_CR : FLASH_CR2; + cr_strt = (1 << FLASH_CR_STRT); + } + + stlink_read_debug32(sl, cr_reg, &val); + val |= cr_strt; + stlink_write_debug32(sl, cr_reg, val); } static inline uint32_t read_flash_sr(stlink_t *sl, unsigned bank) { - uint32_t res, sr_reg; - - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { - sr_reg = (bank==BANK_1)?FLASH_SR:FLASH_SR2; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - sr_reg = get_stm32l0_flash_base(sl) + FLASH_SR_OFF; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - sr_reg = FLASH_F4_SR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - sr_reg = FLASH_F7_SR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - sr_reg = STM32L4_FLASH_SR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - sr_reg = STM32Gx_FLASH_SR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - sr_reg = STM32WB_FLASH_SR; - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - sr_reg = (bank==BANK_1)?FLASH_H7_SR1:FLASH_H7_SR2; - } else { - ELOG("unsupported flash method, abort"); - return(-1); - } - - stlink_read_debug32(sl, sr_reg, &res); - return(res); + uint32_t res, sr_reg; + + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + sr_reg = (bank == BANK_1) ? FLASH_SR : FLASH_SR2; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + sr_reg = get_stm32l0_flash_base(sl) + FLASH_SR_OFF; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + sr_reg = FLASH_F4_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + sr_reg = FLASH_F7_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + sr_reg = STM32L4_FLASH_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + sr_reg = STM32Gx_FLASH_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + sr_reg = STM32WB_FLASH_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + sr_reg = (bank == BANK_1) ? FLASH_H7_SR1 : FLASH_H7_SR2; + } else { + ELOG("method 'read_flash_sr' is unsupported\n"); + return (-1); + } + + stlink_read_debug32(sl, sr_reg, &res); + return (res); +} + +static inline int write_flash_sr(stlink_t *sl, unsigned bank, uint32_t val) { + uint32_t sr_reg; + + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + sr_reg = (bank == BANK_1) ? FLASH_SR : FLASH_SR2; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + sr_reg = get_stm32l0_flash_base(sl) + FLASH_SR_OFF; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + sr_reg = FLASH_F4_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + sr_reg = FLASH_F7_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + sr_reg = STM32L4_FLASH_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + sr_reg = STM32Gx_FLASH_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + sr_reg = STM32WB_FLASH_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + sr_reg = (bank == BANK_1) ? FLASH_H7_SR1 : FLASH_H7_SR2; + } else { + ELOG("method 'write_flash_sr' is unsupported\n"); + return (-1); + } + + return stlink_write_debug32(sl, sr_reg, val); } static inline unsigned int is_flash_busy(stlink_t *sl) { - uint32_t sr_busy_shift; - unsigned int res; - - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_L0)) { - sr_busy_shift = FLASH_SR_BSY; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { - sr_busy_shift = FLASH_F4_SR_BSY; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { - sr_busy_shift = FLASH_F7_SR_BSY; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - sr_busy_shift = STM32L4_FLASH_SR_BSY; - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - sr_busy_shift = STM32Gx_FLASH_SR_BSY; - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - sr_busy_shift = STM32WB_FLASH_SR_BSY; - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - sr_busy_shift = FLASH_H7_SR_QW; - } else { - ELOG("unsupported flash method, abort"); - return(-1); - } - - res = read_flash_sr(sl, BANK_1) & (1 << sr_busy_shift); - - if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL || - (sl->flash_type == STLINK_FLASH_TYPE_H7 && sl->chip_flags & CHIP_F_HAS_DUAL_BANK)) { - res |= read_flash_sr(sl, BANK_2) & (1 << sr_busy_shift); - } - - return(res); + uint32_t sr_busy_shift; + unsigned int res; + + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) || + (sl->flash_type == STLINK_FLASH_TYPE_L0)) { + sr_busy_shift = FLASH_SR_BSY; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { + sr_busy_shift = FLASH_F4_SR_BSY; + } else if (sl->flash_type == STLINK_FLASH_TYPE_F7) { + sr_busy_shift = FLASH_F7_SR_BSY; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + sr_busy_shift = STM32L4_FLASH_SR_BSY; + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + sr_busy_shift = STM32Gx_FLASH_SR_BSY; + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + sr_busy_shift = STM32WB_FLASH_SR_BSY; + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + sr_busy_shift = FLASH_H7_SR_QW; + } else { + ELOG("method 'is_flash_busy' is unsupported\n"); + return (-1); + } + + res = read_flash_sr(sl, BANK_1) & (1 << sr_busy_shift); + + if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL || + (sl->flash_type == STLINK_FLASH_TYPE_H7 && + sl->chip_flags & CHIP_F_HAS_DUAL_BANK)) { + res |= read_flash_sr(sl, BANK_2) & (1 << sr_busy_shift); + } + + return (res); } static void wait_flash_busy(stlink_t *sl) { - // TODO: add some delays here - while (is_flash_busy(sl)) - ; + // TODO: add some delays here + while (is_flash_busy(sl)) + ; } static void wait_flash_busy_progress(stlink_t *sl) { - int i = 0; - fprintf(stdout, "Mass erasing"); - fflush(stdout); - - while (is_flash_busy(sl)) { - usleep(10000); - i++; - - if (i % 100 == 0) { - fprintf(stdout, "."); - fflush(stdout); - } - } - - fprintf(stdout, "\n"); -} - -static int check_flash_error(stlink_t *sl) -{ - uint32_t res = 0; - - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - res = read_flash_sr(sl, BANK_1) & FLASH_SR_ERROR_MASK; - break; - case STLINK_FLASH_TYPE_F7: - res = read_flash_sr(sl, BANK_1) & FLASH_F7_SR_ERROR_MASK; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - res = read_flash_sr(sl, BANK_1) & STM32Gx_FLASH_SR_ERROR_MASK; - break; - case STLINK_FLASH_TYPE_L0: - res = read_flash_sr(sl, BANK_1) & STM32L0_FLASH_SR_ERROR_MASK; - break; - case STLINK_FLASH_TYPE_H7: - res = read_flash_sr(sl, BANK_1) & FLASH_H7_SR_ERROR_MASK; - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - res |= read_flash_sr(sl, BANK_2) & FLASH_H7_SR_ERROR_MASK; - } - if (res) { - // Clear errors - stlink_write_debug32(sl, FLASH_H7_CCR1, res); - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - stlink_write_debug32(sl, FLASH_H7_CCR2, res); - } - } - break; - default: - break; + int i = 0; + fprintf(stdout, "Mass erasing"); + fflush(stdout); + + while (is_flash_busy(sl)) { + usleep(10000); + i++; + + if (i % 100 == 0) { + fprintf(stdout, "."); + fflush(stdout); + } + } + + fprintf(stdout, "\n"); +} + +static void clear_flash_error(stlink_t *sl) { + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F0: + write_flash_sr(sl, BANK_1, FLASH_SR_ERROR_MASK); + break; + case STLINK_FLASH_TYPE_F4: + write_flash_sr(sl, BANK_1, FLASH_F4_SR_ERROR_MASK); + break; + case STLINK_FLASH_TYPE_F7: + write_flash_sr(sl, BANK_1, FLASH_F7_SR_ERROR_MASK); + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + write_flash_sr(sl, BANK_1, STM32Gx_FLASH_SR_ERROR_MASK); + break; + case STLINK_FLASH_TYPE_L0: + write_flash_sr(sl, BANK_1, STM32L0_FLASH_SR_ERROR_MASK); + break; + case STLINK_FLASH_TYPE_L4: + write_flash_sr(sl, BANK_1, STM32L4_FLASH_SR_ERROR_MASK); + break; + case STLINK_FLASH_TYPE_H7: + write_flash_sr(sl, BANK_1, FLASH_H7_SR_ERROR_MASK); + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + write_flash_sr(sl, BANK_2, FLASH_H7_SR_ERROR_MASK); + } + break; + case STLINK_FLASH_TYPE_WB: + write_flash_sr(sl, BANK_1, STM32WB_FLASH_SR_ERROR_MASK); + break; + default: + break; + } +} + +static int check_flash_error(stlink_t *sl) { + uint32_t res = 0; + uint32_t WRPERR, PROGERR, PGAERR; + + WRPERR = PROGERR = PGAERR = 0; + + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + res = read_flash_sr(sl, BANK_1) & FLASH_SR_ERROR_MASK; + if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + res |= read_flash_sr(sl, BANK_2) & FLASH_SR_ERROR_MASK; + } + WRPERR = (1 << FLASH_SR_WRPRT_ERR); + PROGERR = (1 << FLASH_SR_PG_ERR); + break; + case STLINK_FLASH_TYPE_F4: + res = read_flash_sr(sl, BANK_1) & FLASH_F4_SR_ERROR_MASK; + WRPERR = (1 << FLASH_F4_SR_WRPERR); + PGAERR = (1 << FLASH_F4_SR_PGAERR); + break; + case STLINK_FLASH_TYPE_F7: + res = read_flash_sr(sl, BANK_1) & FLASH_F7_SR_ERROR_MASK; + WRPERR = (1 << FLASH_F7_SR_WRP_ERR); + PROGERR = (1 << FLASH_F7_SR_PGP_ERR); + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + res = read_flash_sr(sl, BANK_1) & STM32Gx_FLASH_SR_ERROR_MASK; + WRPERR = (1 << STM32Gx_FLASH_SR_WRPERR); + PROGERR = (1 << STM32Gx_FLASH_SR_PROGERR); + PGAERR = (1 << STM32Gx_FLASH_SR_PGAERR); + break; + case STLINK_FLASH_TYPE_L0: + res = read_flash_sr(sl, BANK_1) & STM32L0_FLASH_SR_ERROR_MASK; + WRPERR = (1 << STM32L0_FLASH_SR_WRPERR); + PROGERR = (1 << STM32L0_FLASH_SR_NOTZEROERR); + PGAERR = (1 << STM32L0_FLASH_SR_PGAERR); + break; + case STLINK_FLASH_TYPE_L4: + res = read_flash_sr(sl, BANK_1) & STM32L4_FLASH_SR_ERROR_MASK; + WRPERR = (1 << STM32L4_FLASH_SR_WRPERR); + PROGERR = (1 << STM32L4_FLASH_SR_PROGERR); + PGAERR = (1 << STM32L4_FLASH_SR_PGAERR); + break; + case STLINK_FLASH_TYPE_H7: + res = read_flash_sr(sl, BANK_1) & FLASH_H7_SR_ERROR_MASK; + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + res |= read_flash_sr(sl, BANK_2) & FLASH_H7_SR_ERROR_MASK; + } + WRPERR = (1 << FLASH_H7_SR_WRPERR); + break; + case STLINK_FLASH_TYPE_WB: + res = read_flash_sr(sl, BANK_1) & STM32WB_FLASH_SR_ERROR_MASK; + WRPERR = (1 << STM32WB_FLASH_SR_WRPERR); + PROGERR = (1 << STM32WB_FLASH_SR_PROGERR); + PGAERR = (1 << STM32WB_FLASH_SR_PGAERR); + break; + default: + break; + } + + if (res) { + if (WRPERR && (WRPERR & res) == WRPERR) { + ELOG("Flash memory is write protected\n"); + res &= ~WRPERR; + } else if (PROGERR && (PROGERR & res) == PROGERR) { + ELOG("Flash memory contains a non-erased value\n"); + res &= ~PROGERR; + } else if (PGAERR && (PGAERR & res) == PGAERR) { + ELOG("Invalid flash address\n"); + res &= ~PGAERR; } if (res) { - ELOG("Flash programming error : %#010x\n", res); - return(-1); - } + ELOG("Flash programming error: %#010x\n", res); + } + return (-1); + } + + return (0); +} + +static void stop_wdg_in_debug(stlink_t *sl) { + uint32_t dbgmcu_cr; + uint32_t set; + uint32_t value; + + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + case STLINK_FLASH_TYPE_G4: + dbgmcu_cr = STM32F0_DBGMCU_CR; + set = + (1 << STM32F0_DBGMCU_CR_IWDG_STOP) | (1 << STM32F0_DBGMCU_CR_WWDG_STOP); + break; + case STLINK_FLASH_TYPE_F4: + case STLINK_FLASH_TYPE_F7: + case STLINK_FLASH_TYPE_L4: + dbgmcu_cr = STM32F4_DBGMCU_APB1FZR1; + set = (1 << STM32F4_DBGMCU_APB1FZR1_IWDG_STOP) | + (1 << STM32F4_DBGMCU_APB1FZR1_WWDG_STOP); + break; + case STLINK_FLASH_TYPE_L0: + case STLINK_FLASH_TYPE_G0: + dbgmcu_cr = STM32L0_DBGMCU_APB1_FZ; + set = (1 << STM32L0_DBGMCU_APB1_FZ_IWDG_STOP) | + (1 << STM32L0_DBGMCU_APB1_FZ_WWDG_STOP); + break; + case STLINK_FLASH_TYPE_H7: + dbgmcu_cr = STM32H7_DBGMCU_APB1HFZ; + set = (1 << STM32H7_DBGMCU_APB1HFZ_IWDG_STOP); + break; + case STLINK_FLASH_TYPE_WB: + dbgmcu_cr = STM32WB_DBGMCU_APB1FZR1; + set = (1 << STM32WB_DBGMCU_APB1FZR1_IWDG_STOP) | + (1 << STM32WB_DBGMCU_APB1FZR1_WWDG_STOP); + break; + default: + return; + } + + if (!stlink_read_debug32(sl, dbgmcu_cr, &value)) { + stlink_write_debug32(sl, dbgmcu_cr, value | set); + } +} + +static void set_dma_state(stlink_t *sl, flash_loader_t *fl, int bckpRstr) { + uint32_t rcc, rcc_dma_mask, value; + + rcc = rcc_dma_mask = value = 0; + + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + rcc = STM32F1_RCC_AHBENR; + rcc_dma_mask = STM32F1_RCC_DMAEN; + break; + case STLINK_FLASH_TYPE_F4: + case STLINK_FLASH_TYPE_F7: + rcc = STM32F4_RCC_AHB1ENR; + rcc_dma_mask = STM32F4_RCC_DMAEN; + break; + case STLINK_FLASH_TYPE_G0: + rcc = STM32G0_RCC_AHBENR; + rcc_dma_mask = STM32G0_RCC_DMAEN; + break; + case STLINK_FLASH_TYPE_G4: + case STLINK_FLASH_TYPE_L4: + rcc = STM32G4_RCC_AHB1ENR; + rcc_dma_mask = STM32G4_RCC_DMAEN; + break; + case STLINK_FLASH_TYPE_L0: + rcc = STM32L0_RCC_AHBENR; + rcc_dma_mask = STM32L0_RCC_DMAEN; + break; + case STLINK_FLASH_TYPE_H7: + rcc = STM32H7_RCC_AHB1ENR; + rcc_dma_mask = STM32H7_RCC_DMAEN; + break; + case STLINK_FLASH_TYPE_WB: + rcc = STM32WB_RCC_AHB1ENR; + rcc_dma_mask = STM32WB_RCC_DMAEN; + break; + default: + return; + } - return(0); + if (!stlink_read_debug32(sl, rcc, &value)) { + if (bckpRstr) { + value = (value & (~rcc_dma_mask)) | fl->rcc_dma_bkp; + } else { + fl->rcc_dma_bkp = value & rcc_dma_mask; + value &= ~rcc_dma_mask; + } + stlink_write_debug32(sl, rcc, value); + } } static inline void write_flash_ar(stlink_t *sl, uint32_t n, unsigned bank) { - stlink_write_debug32(sl, (bank==BANK_1)?FLASH_AR:FLASH_AR2, n); + stlink_write_debug32(sl, (bank == BANK_1) ? FLASH_AR : FLASH_AR2, n); } -static inline void write_flash_cr_psiz(stlink_t *sl, uint32_t n, unsigned bank) { - uint32_t cr_reg, psize_shift; - uint32_t x = read_flash_cr(sl, bank); +static inline void write_flash_cr_psiz(stlink_t *sl, uint32_t n, + unsigned bank) { + uint32_t cr_reg, psize_shift; + uint32_t x = read_flash_cr(sl, bank); - if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = (bank==BANK_1)?FLASH_H7_CR1:FLASH_H7_CR2; - psize_shift = FLASH_H7_CR_PSIZE; - } else { - cr_reg = FLASH_F4_CR; - psize_shift = 8; - } + if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2; + psize_shift = FLASH_H7_CR_PSIZE; + } else { + cr_reg = FLASH_F4_CR; + psize_shift = 8; + } - x &= ~(0x03 << psize_shift); - x |= (n << psize_shift); + x &= ~(0x03 << psize_shift); + x |= (n << psize_shift); #if DEBUG_FLASH - fprintf(stdout, "PSIZ:0x%x 0x%x\n", x, n); + fprintf(stdout, "PSIZ:0x%x 0x%x\n", x, n); #endif - stlink_write_debug32(sl, cr_reg, x); + stlink_write_debug32(sl, cr_reg, x); } static inline void write_flash_cr_snb(stlink_t *sl, uint32_t n, unsigned bank) { - uint32_t cr_reg, snb_mask, snb_shift, ser_shift; - uint32_t x = read_flash_cr(sl, bank); - - if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - cr_reg = (bank==BANK_1)?FLASH_H7_CR1:FLASH_H7_CR2; - snb_mask = FLASH_H7_CR_SNB_MASK; - snb_shift = FLASH_H7_CR_SNB; - ser_shift = FLASH_H7_CR_SER; - } else { - cr_reg = FLASH_F4_CR; - snb_mask = FLASH_F4_CR_SNB_MASK; - snb_shift = FLASH_F4_CR_SNB; - ser_shift = FLASH_F4_CR_SER; - } - - x &= ~snb_mask; - x |= (n << snb_shift); - x |= (1 << ser_shift); + uint32_t cr_reg, snb_mask, snb_shift, ser_shift; + uint32_t x = read_flash_cr(sl, bank); + + if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + cr_reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2; + snb_mask = FLASH_H7_CR_SNB_MASK; + snb_shift = FLASH_H7_CR_SNB; + ser_shift = FLASH_H7_CR_SER; + } else { + cr_reg = FLASH_F4_CR; + snb_mask = FLASH_F4_CR_SNB_MASK; + snb_shift = FLASH_F4_CR_SNB; + ser_shift = FLASH_F4_CR_SER; + } + + x &= ~snb_mask; + x |= (n << snb_shift); + x |= (1 << ser_shift); #if DEBUG_FLASH - fprintf(stdout, "SNB:0x%x 0x%x\n", x, n); + fprintf(stdout, "SNB:0x%x 0x%x\n", x, n); #endif - stlink_write_debug32(sl, cr_reg, x); + stlink_write_debug32(sl, cr_reg, x); } static inline void write_flash_cr_bker_pnb(stlink_t *sl, uint32_t n) { - stlink_write_debug32(sl, STM32L4_FLASH_SR, 0xFFFFFFFF & ~(1 << STM32L4_FLASH_SR_BSY)); - uint32_t x = read_flash_cr(sl, BANK_1); - x &= ~STM32L4_FLASH_CR_OPBITS; - x &= ~STM32L4_FLASH_CR_PAGEMASK; - x &= ~(1 << STM32L4_FLASH_CR_MER1); - x &= ~(1 << STM32L4_FLASH_CR_MER2); - x |= (n << STM32L4_FLASH_CR_PNB); - x |= (uint32_t)(1lu << STM32L4_FLASH_CR_PER); + stlink_write_debug32(sl, STM32L4_FLASH_SR, + 0xFFFFFFFF & ~(1 << STM32L4_FLASH_SR_BSY)); + uint32_t x = read_flash_cr(sl, BANK_1); + x &= ~STM32L4_FLASH_CR_OPBITS; + x &= ~STM32L4_FLASH_CR_PAGEMASK; + x &= ~(1 << STM32L4_FLASH_CR_MER1); + x &= ~(1 << STM32L4_FLASH_CR_MER2); + x |= (n << STM32L4_FLASH_CR_PNB); + x |= (uint32_t)(1lu << STM32L4_FLASH_CR_PER); #if DEBUG_FLASH - fprintf(stdout, "BKER:PNB:0x%x 0x%x\n", x, n); + fprintf(stdout, "BKER:PNB:0x%x 0x%x\n", x, n); #endif - stlink_write_debug32(sl, STM32L4_FLASH_CR, x); + stlink_write_debug32(sl, STM32L4_FLASH_CR, x); } // Delegates to the backends... void stlink_close(stlink_t *sl) { - DLOG("*** stlink_close ***\n"); + DLOG("*** stlink_close ***\n"); - if (!sl) { - return; - } + if (!sl) { + return; + } - sl->backend->close(sl); - free(sl); + sl->backend->close(sl); + free(sl); } int stlink_exit_debug_mode(stlink_t *sl) { - int ret; + int ret; - DLOG("*** stlink_exit_debug_mode ***\n"); - ret = stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY); + DLOG("*** stlink_exit_debug_mode ***\n"); + ret = stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY); - if (ret == -1) { - return(ret); - } + if (ret == -1) { + return (ret); + } - return(sl->backend->exit_debug_mode(sl)); + return (sl->backend->exit_debug_mode(sl)); } int stlink_enter_swd_mode(stlink_t *sl) { - DLOG("*** stlink_enter_swd_mode ***\n"); - return(sl->backend->enter_swd_mode(sl)); + DLOG("*** stlink_enter_swd_mode ***\n"); + return (sl->backend->enter_swd_mode(sl)); } // Force the core into the debug mode -> halted state. int stlink_force_debug(stlink_t *sl) { - DLOG("*** stlink_force_debug_mode ***\n"); - return(sl->backend->force_debug(sl)); + DLOG("*** stlink_force_debug_mode ***\n"); + int res = sl->backend->force_debug(sl); + // Stop the watchdogs in the halted state for suppress target reboot + stop_wdg_in_debug(sl); + return (res); } int stlink_exit_dfu_mode(stlink_t *sl) { - DLOG("*** stlink_exit_dfu_mode ***\n"); - return(sl->backend->exit_dfu_mode(sl)); + DLOG("*** stlink_exit_dfu_mode ***\n"); + return (sl->backend->exit_dfu_mode(sl)); } int stlink_core_id(stlink_t *sl) { - int ret; + int ret; - DLOG("*** stlink_core_id ***\n"); - ret = sl->backend->core_id(sl); + DLOG("*** stlink_core_id ***\n"); + ret = sl->backend->core_id(sl); - if (ret == -1) { - ELOG("Failed to read core_id\n"); - return(ret); - } + if (ret == -1) { + ELOG("Failed to read core_id\n"); + return (ret); + } - if (sl->verbose > 2) { - stlink_print_data(sl); - } + if (sl->verbose > 2) { + stlink_print_data(sl); + } - DLOG("core_id = 0x%08x\n", sl->core_id); - return(ret); + DLOG("core_id = 0x%08x\n", sl->core_id); + return (ret); } // stlink_chip_id() is called by stlink_load_device_params() // do not call this procedure directly. int stlink_chip_id(stlink_t *sl, uint32_t *chip_id) { - int ret; - - if (sl->core_id == STM32H7_CORE_ID) { - // STM32H7 chipid in 0x5c001000 (RM0433 pg3189) - ret = stlink_read_debug32(sl, 0x5c001000, chip_id); - } else { - // default chipid address - ret = stlink_read_debug32(sl, 0xE0042000, chip_id); - } - - if (ret == -1) { - return(ret); - } - - if (*chip_id == 0) { - // STM32H7 chipid in 0x5c001000 (RM0433 pg3189) - ret = stlink_read_debug32(sl, 0x5c001000, chip_id); - } - - if (*chip_id == 0) { - // Try Corex M0 DBGMCU_IDCODE register address - ret = stlink_read_debug32(sl, 0x40015800, chip_id); - } - - return(ret); + int ret; + cortex_m3_cpuid_t cpu_id; + + // Read the CPU ID to determine where to read the core id + if (stlink_cpu_id(sl, &cpu_id) || + cpu_id.implementer_id != STLINK_REG_CMx_CPUID_IMPL_ARM) { + ELOG("Can not connect to target. Please use \'connect under reset\' and " + "try again\n"); + return -1; + } + + /* + * the chip_id register in the reference manual have + * DBGMCU_IDCODE / DBG_IDCODE name + * + */ + + if ((sl->core_id == STM32H7_CORE_ID || sl->core_id == STM32H7_CORE_ID_JTAG) && + cpu_id.part == STLINK_REG_CMx_CPUID_PARTNO_CM7) { + // STM32H7 chipid in 0x5c001000 (RM0433 pg3189) + ret = stlink_read_debug32(sl, 0x5c001000, chip_id); + } else if (cpu_id.part == STLINK_REG_CMx_CPUID_PARTNO_CM0 || + cpu_id.part == STLINK_REG_CMx_CPUID_PARTNO_CM0P) { + // STM32F0 (RM0091, pg914; RM0360, pg713) + // STM32L0 (RM0377, pg813; RM0367, pg915; RM0376, pg917) + // STM32G0 (RM0444, pg1367) + ret = stlink_read_debug32(sl, 0x40015800, chip_id); + } else if (cpu_id.part == STLINK_REG_CMx_CPUID_PARTNO_CM33) { + // STM32L5 (RM0438, pg2157) + ret = stlink_read_debug32(sl, 0xE0044000, chip_id); + } else /* СM3, СM4, CM7 */ { + // default chipid address + + // STM32F1 (RM0008, pg1087; RM0041, pg681) + // STM32F2 (RM0033, pg1326) + // STM32F3 (RM0316, pg1095; RM0313, pg874) + // STM32F7 (RM0385, pg1676; RM0410, pg1912) + // STM32L1 (RM0038, pg861) + // STM32L4 (RM0351, pg1840; RM0394, pg1560) + // STM32G4 (RM0440, pg2086) + // STM32WB (RM0434, pg1406) + ret = stlink_read_debug32(sl, 0xE0042000, chip_id); + } + + if (ret || !(*chip_id)) { + *chip_id = 0; + ELOG("Could not find chip id!\n"); + } else { + *chip_id = (*chip_id) & 0xfff; + + // Fix chip_id for F4 rev A errata, read CPU ID, as CoreID is the same for + // F2/F4 + if (*chip_id == 0x411 && cpu_id.part == STLINK_REG_CMx_CPUID_PARTNO_CM4) { + *chip_id = 0x413; + } + } + + return (ret); } /** - * Cortex m3 tech ref manual, CPUID register description + * Cortex M tech ref manual, CPUID register description * @param sl stlink context * @param cpuid pointer to the result object */ int stlink_cpu_id(stlink_t *sl, cortex_m3_cpuid_t *cpuid) { - uint32_t raw; - - if (stlink_read_debug32(sl, STLINK_REG_CM3_CPUID, &raw)) { - cpuid->implementer_id = 0; - cpuid->variant = 0; - cpuid->part = 0; - cpuid->revision = 0; - return(-1); - } + uint32_t raw; - cpuid->implementer_id = (raw >> 24) & 0x7f; - cpuid->variant = (raw >> 20) & 0xf; - cpuid->part = (raw >> 4) & 0xfff; - cpuid->revision = raw & 0xf; - return(0); + if (stlink_read_debug32(sl, STLINK_REG_CM3_CPUID, &raw)) { + cpuid->implementer_id = 0; + cpuid->variant = 0; + cpuid->part = 0; + cpuid->revision = 0; + return (-1); + } + + cpuid->implementer_id = (raw >> 24) & 0x7f; + cpuid->variant = (raw >> 20) & 0xf; + cpuid->part = (raw >> 4) & 0xfff; + cpuid->revision = raw & 0xf; + return (0); } /** @@ -1275,219 +1581,268 @@ int stlink_cpu_id(stlink_t *sl, cortex_m3_cpuid_t *cpuid) { * @return 0 for success, or -1 for unsupported core type. */ int stlink_load_device_params(stlink_t *sl) { - // This seems to normally work so is unnecessary info for a normal user. - // Demoted to debug. -- REW - DLOG("Loading device parameters....\n"); - const struct stlink_chipid_params *params = NULL; - stlink_core_id(sl); - uint32_t chip_id = 0; - uint32_t flash_size; - - stlink_chip_id(sl, &chip_id); - sl->chip_id = chip_id & 0xfff; - - // Fix chip_id for F4 rev A errata , Read CPU ID, as CoreID is the same for F2/F4 - if (sl->chip_id == 0x411) { - uint32_t cpuid; - stlink_read_debug32(sl, 0xE000ED00, &cpuid); - - if ((cpuid & 0xfff0) == 0xc240) { - sl->chip_id = 0x413; - } - } - - params = stlink_chipid_get_params(sl->chip_id); - - if (params == NULL) { - WLOG("unknown chip id! %#x\n", chip_id); - return(-1); - } - - if (params->flash_type == STLINK_FLASH_TYPE_UNKNOWN) { - WLOG("Invalid flash type, please check device declaration\n"); - sl->flash_size = 0; - return(0); - } - - // These are fixed... - sl->flash_base = STM32_FLASH_BASE; - sl->sram_base = STM32_SRAM_BASE; - stlink_read_debug32(sl, (params->flash_size_reg) & ~3, &flash_size); - - if (params->flash_size_reg & 2) { - flash_size = flash_size >> 16; - } - - flash_size = flash_size & 0xffff; - - if ((sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM || - sl->chip_id == STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW || - sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM_PLUS) && (flash_size == 0)) { - sl->flash_size = 128 * 1024; - } else if (sl->chip_id == STLINK_CHIPID_STM32_L1_CAT2) { - sl->flash_size = (flash_size & 0xff) * 1024; - } else if ((sl->chip_id & 0xFFF) == STLINK_CHIPID_STM32_L1_HIGH) { - // 0 is 384k and 1 is 256k - if (flash_size == 0) { - sl->flash_size = 384 * 1024; - } else { - sl->flash_size = 256 * 1024; - } + // This seems to normally work so is unnecessary info for a normal user. + // Demoted to debug. -- REW + DLOG("Loading device parameters....\n"); + const struct stlink_chipid_params *params = NULL; + stlink_core_id(sl); + uint32_t flash_size; + + if (stlink_chip_id(sl, &sl->chip_id)) { + return (-1); + } + + params = stlink_chipid_get_params(sl->chip_id); + + if (params == NULL) { + WLOG("unknown chip id! %#x\n", sl->chip_id); + return (-1); + } + + if (params->flash_type == STLINK_FLASH_TYPE_UNKNOWN) { + WLOG("Invalid flash type, please check device declaration\n"); + sl->flash_size = 0; + return (0); + } + + // These are fixed... + sl->flash_base = STM32_FLASH_BASE; + sl->sram_base = STM32_SRAM_BASE; + stlink_read_debug32(sl, (params->flash_size_reg) & ~3, &flash_size); + + if (params->flash_size_reg & 2) { + flash_size = flash_size >> 16; + } + + flash_size = flash_size & 0xffff; + + if ((sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM || + sl->chip_id == STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW || + sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM_PLUS) && + (flash_size == 0)) { + sl->flash_size = 128 * 1024; + } else if (sl->chip_id == STLINK_CHIPID_STM32_L1_CAT2) { + sl->flash_size = (flash_size & 0xff) * 1024; + } else if ((sl->chip_id & 0xFFF) == STLINK_CHIPID_STM32_L1_HIGH) { + // 0 is 384k and 1 is 256k + if (flash_size == 0) { + sl->flash_size = 384 * 1024; } else { - sl->flash_size = flash_size * 1024; - } - - sl->flash_type = params->flash_type; - sl->flash_pgsz = params->flash_pagesize; - sl->sram_size = params->sram_size; - sl->sys_base = params->bootrom_base; - sl->sys_size = params->bootrom_size; - sl->option_base = params->option_base; - sl->option_size = params->option_size; - sl->chip_flags = params->flags; - - // medium and low devices have the same chipid. ram size depends on flash size. - // STM32F100xx datasheet Doc ID 16455 Table 2 - if (sl->chip_id == STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW && sl->flash_size < 64 * 1024) { - sl->sram_size = 0x1000; - } - - if (sl->chip_id == STLINK_CHIPID_STM32_G4_CAT3) { - uint32_t flash_optr; - stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, &flash_optr); + sl->flash_size = 256 * 1024; + } + } else { + sl->flash_size = flash_size * 1024; + } + + sl->flash_type = params->flash_type; + sl->flash_pgsz = params->flash_pagesize; + sl->sram_size = params->sram_size; + sl->sys_base = params->bootrom_base; + sl->sys_size = params->bootrom_size; + sl->option_base = params->option_base; + sl->option_size = params->option_size; + sl->chip_flags = params->flags; + + // medium and low devices have the same chipid. ram size depends on flash + // size. STM32F100xx datasheet Doc ID 16455 Table 2 + if (sl->chip_id == STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW && + sl->flash_size < 64 * 1024) { + sl->sram_size = 0x1000; + } + + if (sl->chip_id == STLINK_CHIPID_STM32_G4_CAT3) { + uint32_t flash_optr; + stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, &flash_optr); + + if (!(flash_optr & (1 << STM32G4_FLASH_OPTR_DBANK))) { + sl->flash_pgsz <<= 1; + } + } + + // H7 devices with small flash has one bank + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK && + sl->flash_type == STLINK_FLASH_TYPE_H7) { + if ((flash_size / sl->flash_pgsz) <= 1) + sl->chip_flags &= ~CHIP_F_HAS_DUAL_BANK; + } + + ILOG("%s: %u KiB SRAM, %u KiB flash in at least %u %s pages.\n", + params->description, (unsigned)(sl->sram_size / 1024), + (unsigned)(sl->flash_size / 1024), + (sl->flash_pgsz < 1024) ? (unsigned)(sl->flash_pgsz) + : (unsigned)(sl->flash_pgsz / 1024), + (sl->flash_pgsz < 1024) ? "byte" : "KiB"); + + return (0); +} - if (!(flash_optr & (1 << STM32G4_FLASH_OPTR_DBANK))) { sl->flash_pgsz <<= 1; } - } +int stlink_jtag_reset(stlink_t *sl, int value) { + DLOG("*** stlink_jtag_reset ***\n"); + return (sl->backend->jtag_reset(sl, value)); +} - // H7 devices with small flash has one bank - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK && sl->flash_type == STLINK_FLASH_TYPE_H7) { - if ((flash_size/sl->flash_pgsz) <= 1) - sl->chip_flags &= ~CHIP_F_HAS_DUAL_BANK; +int stlink_soft_reset(stlink_t *sl, int halt_on_reset) { + int ret; + unsigned timeout; + uint32_t dhcsr, dfsr; + + DLOG("*** stlink_soft_reset %s***\n", halt_on_reset ? "(halt) " : ""); + + // halt core and enable debugging (if not already done) + // C_DEBUGEN is required to Halt on reset (DDI0337E, p. 10-6) + stlink_write_debug32(sl, STLINK_REG_DHCSR, + STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_HALT | + STLINK_REG_DHCSR_C_DEBUGEN); + + // enable Halt on reset by set VC_CORERESET and TRCENA (DDI0337E, p. 10-10) + if (halt_on_reset) { + stlink_write_debug32( + sl, STLINK_REG_CM3_DEMCR, + STLINK_REG_CM3_DEMCR_TRCENA | STLINK_REG_CM3_DEMCR_VC_HARDERR | + STLINK_REG_CM3_DEMCR_VC_BUSERR | STLINK_REG_CM3_DEMCR_VC_CORERESET); + + // clear VCATCH in the DFSR register + stlink_write_debug32(sl, STLINK_REG_DFSR, STLINK_REG_DFSR_VCATCH); + } else { + stlink_write_debug32(sl, STLINK_REG_CM3_DEMCR, + STLINK_REG_CM3_DEMCR_TRCENA | + STLINK_REG_CM3_DEMCR_VC_HARDERR | + STLINK_REG_CM3_DEMCR_VC_BUSERR); + } + + // clear S_RESET_ST in the DHCSR register + stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); + + // soft reset (core reset) by SYSRESETREQ (DDI0337E, p. 8-23) + ret = stlink_write_debug32(sl, STLINK_REG_AIRCR, + STLINK_REG_AIRCR_VECTKEY | + STLINK_REG_AIRCR_SYSRESETREQ); + if (ret) { + ELOG("Soft reset failed: error write to AIRCR\n"); + return (ret); + } + + // waiting for a reset within 500ms + // DDI0337E, p. 10-4, Debug Halting Control and Status Register + timeout = time_ms() + 500; + while (time_ms() < timeout) { + // DDI0337E, p. 10-4, Debug Halting Control and Status Register + dhcsr = STLINK_REG_DHCSR_S_RESET_ST; + stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); + if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) { + if (halt_on_reset) { + // waiting halt by the SYSRESETREQ exception + // DDI0403E, p. C1-699, Debug Fault Status Register + dfsr = 0; + stlink_read_debug32(sl, STLINK_REG_DFSR, &dfsr); + if ((dfsr & STLINK_REG_DFSR_VCATCH) == 0) { + continue; + } + } + timeout = 0; + break; } + } -#if 0 - // Old code -- REW - ILOG("Device connected is: %s, id %#x\n", params->description, chip_id); - // TODO: make note of variable page size here..... - ILOG("SRAM size: %#x bytes (%d KiB), Flash: %#x bytes (%d KiB) in pages of %u bytes\n", - sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024, - (unsigned int)sl->flash_pgsz); -#else - ILOG("%s: %u KiB SRAM, %u KiB flash in at least %u %s pages.\n", - params->description, (unsigned)(sl->sram_size / 1024), (unsigned)(sl->flash_size / 1024), - (sl->flash_pgsz < 1024) ? (unsigned)(sl->flash_pgsz) : (unsigned)(sl->flash_pgsz / 1024), - (sl->flash_pgsz < 1024) ? "byte" : "KiB"); -#endif - return(0); -} + // reset DFSR register. DFSR is power-on reset only (DDI0337H, p. 7-5) + stlink_write_debug32(sl, STLINK_REG_DFSR, STLINK_REG_DFSR_CLEAR); -int stlink_reset(stlink_t *sl) { - DLOG("*** stlink_reset ***\n"); - return(sl->backend->reset(sl)); -} + if (timeout) { + ELOG("Soft reset failed: timeout\n"); + return (-1); + } -int stlink_jtag_reset(stlink_t *sl, int value) { - DLOG("*** stlink_jtag_reset ***\n"); - return(sl->backend->jtag_reset(sl, value)); + return (0); } -int stlink_soft_reset(stlink_t *sl, int halt_on_reset) { - int ret; - unsigned timeout; - uint32_t dhcsr, dfsr; - - DLOG("*** stlink_soft_reset %s***\n", halt_on_reset?"(halt) ":""); +int stlink_reset(stlink_t *sl, enum reset_type type) { + uint32_t dhcsr; + unsigned timeout; - // halt core and enable debugging (if not already done) - // C_DEBUGEN is required to Halt on reset (DDI0337E, p. 10-6) - stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | - STLINK_REG_DHCSR_C_HALT | STLINK_REG_DHCSR_C_DEBUGEN); + DLOG("*** stlink_reset ***\n"); - // enable Halt on reset by set VC_CORERESET and TRCENA (DDI0337E, p. 10-10) - if (halt_on_reset) { - stlink_write_debug32(sl, STLINK_REG_CM3_DEMCR, STLINK_REG_CM3_DEMCR_TRCENA | - STLINK_REG_CM3_DEMCR_VC_HARDERR | STLINK_REG_CM3_DEMCR_VC_BUSERR | - STLINK_REG_CM3_DEMCR_VC_CORERESET); + if (type == RESET_AUTO) { + // clear S_RESET_ST in DHCSR register for reset state detection + stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); + } - // clear VCATCH in the DFSR register - stlink_write_debug32(sl, STLINK_REG_DFSR, STLINK_REG_DFSR_VCATCH); - } else { - stlink_write_debug32(sl, STLINK_REG_CM3_DEMCR, STLINK_REG_CM3_DEMCR_TRCENA | - STLINK_REG_CM3_DEMCR_VC_HARDERR | STLINK_REG_CM3_DEMCR_VC_BUSERR); + if (type == RESET_HARD || type == RESET_AUTO) { + // hardware target reset + if (sl->version.stlink_v > 1) { + stlink_jtag_reset(sl, STLINK_JTAG_DRIVE_NRST_LOW); + // minimum reset pulse duration of 20 us (RM0008, 8.1.2 Power reset) + usleep(100); + stlink_jtag_reset(sl, STLINK_JTAG_DRIVE_NRST_HIGH); + } + if (sl->backend->reset(sl)) { + return (-1); } + usleep(10000); + } - // clear S_RESET_ST in the DHCSR register + if (type == RESET_AUTO) { + /* Check if the S_RESET_ST bit is set in DHCSR + * This means that a reset has occurred + * DDI0337E, p. 10-4, Debug Halting Control and Status Register */ + + dhcsr = 0; stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); + if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) { + // reset not done yet + // try reset through AIRCR so that NRST does not need to be connected - // soft reset (core reset) by SYSRESETREQ (DDI0337E, p. 8-23) - ret = stlink_write_debug32(sl, STLINK_REG_AIRCR, STLINK_REG_AIRCR_VECTKEY | - STLINK_REG_AIRCR_SYSRESETREQ); - if (ret) { - ELOG("Soft reset failed: error write to AIRCR\n"); - return(ret); + WLOG("NRST is not connected\n"); + DLOG("Using reset through SYSRESETREQ\n"); + return stlink_soft_reset(sl, 0); } - // waiting for a reset within 500ms - // DDI0337E, p. 10-4, Debug Halting Control and Status Register + // waiting for reset the S_RESET_ST bit within 500ms timeout = time_ms() + 500; while (time_ms() < timeout) { - // DDI0337E, p. 10-4, Debug Halting Control and Status Register - dhcsr = STLINK_REG_DHCSR_S_RESET_ST; - stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); - if ((dhcsr&STLINK_REG_DHCSR_S_RESET_ST) == 0) { - if (halt_on_reset) { - // waiting halt by the SYSRESETREQ exception - // DDI0403E, p. C1-699, Debug Fault Status Register - dfsr = 0; - stlink_read_debug32(sl, STLINK_REG_DFSR, &dfsr); - if ((dfsr&STLINK_REG_DFSR_VCATCH) == 0) { - continue; - } - } - timeout = 0; - break; - } + dhcsr = STLINK_REG_DHCSR_S_RESET_ST; + stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); + if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) + return (0); } - // reset DFSR register. DFSR is power-on reset only (DDI0337H, p. 7-5) - stlink_write_debug32(sl, STLINK_REG_DFSR, STLINK_REG_DFSR_CLEAR); + return (-1); + } - if (timeout) { - ELOG("Soft reset failed: timeout\n"); - return(-1); - } + if (type == RESET_SOFT || type == RESET_SOFT_AND_HALT) { + return stlink_soft_reset(sl, (type == RESET_SOFT_AND_HALT)); + } - return(0); + return (0); } -int stlink_run(stlink_t *sl) { - struct stlink_reg rr; - DLOG("*** stlink_run ***\n"); +int stlink_run(stlink_t *sl, enum run_type type) { + struct stlink_reg rr; + DLOG("*** stlink_run ***\n"); - /* Make sure we are in Thumb mode - * Cortex-M chips don't support ARM mode instructions - * xPSR may be incorrect if the vector table has invalid data */ - stlink_read_reg(sl, 16, &rr); - if ((rr.xpsr & (1 << 24)) == 0) { - ILOG("Go to Thumb mode\n"); - stlink_write_reg(sl, rr.xpsr | (1 << 24), 16); - } + /* Make sure we are in Thumb mode + * Cortex-M chips don't support ARM mode instructions + * xPSR may be incorrect if the vector table has invalid data */ + stlink_read_reg(sl, 16, &rr); + if ((rr.xpsr & (1 << 24)) == 0) { + ILOG("Go to Thumb mode\n"); + stlink_write_reg(sl, rr.xpsr | (1 << 24), 16); + } - return(sl->backend->run(sl)); + return (sl->backend->run(sl, type)); } int stlink_set_swdclk(stlink_t *sl, int freq_khz) { - DLOG("*** set_swdclk ***\n"); - return(sl->backend->set_swdclk(sl, freq_khz)); + DLOG("*** set_swdclk ***\n"); + return (sl->backend->set_swdclk(sl, freq_khz)); } int stlink_status(stlink_t *sl) { - int ret; + int ret; - DLOG("*** stlink_status ***\n"); - ret = sl->backend->status(sl); - stlink_core_stat(sl); - return(ret); + DLOG("*** stlink_status ***\n"); + ret = sl->backend->status(sl); + stlink_core_stat(sl); + return (ret); } /** @@ -1496,1133 +1851,1192 @@ int stlink_status(stlink_t *sl) { * @param slv output parsed version object */ void _parse_version(stlink_t *sl, stlink_version_t *slv) { - sl->version.flags = 0; - - if (sl->version.stlink_v < 3) { - uint32_t b0 = sl->q_buf[0]; // lsb - uint32_t b1 = sl->q_buf[1]; - uint32_t b2 = sl->q_buf[2]; - uint32_t b3 = sl->q_buf[3]; - uint32_t b4 = sl->q_buf[4]; - uint32_t b5 = sl->q_buf[5]; // msb - - // b0 b1 || b2 b3 | b4 b5 - // 4b | 6b | 6b || 2B | 2B - // stlink_v | jtag_v | swim_v || st_vid | stlink_pid - - slv->stlink_v = (b0 & 0xf0) >> 4; - slv->jtag_v = ((b0 & 0x0f) << 2) | ((b1 & 0xc0) >> 6); - slv->swim_v = b1 & 0x3f; - slv->st_vid = (b3 << 8) | b2; - slv->stlink_pid = (b5 << 8) | b4; - - // ST-LINK/V1 from J11 switch to api-v2 (and support SWD) - if (slv->stlink_v == 1) { - slv->jtag_api = slv->jtag_v > 11 ? STLINK_JTAG_API_V2 : STLINK_JTAG_API_V1; - } else { - slv->jtag_api = STLINK_JTAG_API_V2; - - // preferred API to get last R/W status from J15 - if (sl->version.jtag_v >= 15) { - sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2; - } - - if (sl->version.jtag_v >= 13) { - sl->version.flags |= STLINK_F_HAS_TRACE; - sl->max_trace_freq = STLINK_V2_MAX_TRACE_FREQUENCY; - } - } + sl->version.flags = 0; + + if (sl->version.stlink_v < 3) { + uint32_t b0 = sl->q_buf[0]; // lsb + uint32_t b1 = sl->q_buf[1]; + uint32_t b2 = sl->q_buf[2]; + uint32_t b3 = sl->q_buf[3]; + uint32_t b4 = sl->q_buf[4]; + uint32_t b5 = sl->q_buf[5]; // msb + + // b0 b1 || b2 b3 | b4 b5 + // 4b | 6b | 6b || 2B | 2B + // stlink_v | jtag_v | swim_v || st_vid | stlink_pid + + slv->stlink_v = (b0 & 0xf0) >> 4; + slv->jtag_v = ((b0 & 0x0f) << 2) | ((b1 & 0xc0) >> 6); + slv->swim_v = b1 & 0x3f; + slv->st_vid = (b3 << 8) | b2; + slv->stlink_pid = (b5 << 8) | b4; + + // ST-LINK/V1 from J11 switch to api-v2 (and support SWD) + if (slv->stlink_v == 1) { + slv->jtag_api = + slv->jtag_v > 11 ? STLINK_JTAG_API_V2 : STLINK_JTAG_API_V1; } else { - // V3 uses different version format, for reference see OpenOCD source - // (that was written from docs available from ST under NDA): - // https://github.com/ntfreak/openocd/blob/a6dacdff58ef36fcdac00c53ec27f19de1fbce0d/src/jtag/drivers/stlink_usb.c#L965 - slv->stlink_v = sl->q_buf[0]; - slv->swim_v = sl->q_buf[1]; - slv->jtag_v = sl->q_buf[2]; - slv->st_vid = (uint32_t)((sl->q_buf[9] << 8) | sl->q_buf[8]); - slv->stlink_pid = (uint32_t)((sl->q_buf[11] << 8) | sl->q_buf[10]); - slv->jtag_api = STLINK_JTAG_API_V3; - /* preferred API to get last R/W status */ + slv->jtag_api = STLINK_JTAG_API_V2; + + // preferred API to get last R/W status from J15 + if (sl->version.jtag_v >= 15) { sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2; - sl->version.flags |= STLINK_F_HAS_TRACE; - sl->max_trace_freq = STLINK_V3_MAX_TRACE_FREQUENCY; - } + } - return; + if (sl->version.jtag_v >= 13) { + sl->version.flags |= STLINK_F_HAS_TRACE; + sl->max_trace_freq = STLINK_V2_MAX_TRACE_FREQUENCY; + } + } + } else { + // V3 uses different version format, for reference see OpenOCD source + // (that was written from docs available from ST under NDA): + // https://github.com/ntfreak/openocd/blob/a6dacdff58ef36fcdac00c53ec27f19de1fbce0d/src/jtag/drivers/stlink_usb.c#L965 + slv->stlink_v = sl->q_buf[0]; + slv->swim_v = sl->q_buf[1]; + slv->jtag_v = sl->q_buf[2]; + slv->st_vid = (uint32_t)((sl->q_buf[9] << 8) | sl->q_buf[8]); + slv->stlink_pid = (uint32_t)((sl->q_buf[11] << 8) | sl->q_buf[10]); + slv->jtag_api = STLINK_JTAG_API_V3; + /* preferred API to get last R/W status */ + sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2; + sl->version.flags |= STLINK_F_HAS_TRACE; + sl->max_trace_freq = STLINK_V3_MAX_TRACE_FREQUENCY; + } + + return; } int stlink_version(stlink_t *sl) { - DLOG("*** looking up stlink version\n"); + DLOG("*** looking up stlink version\n"); - if (sl->backend->version(sl)) { - return(-1); - } + if (sl->backend->version(sl)) { + return (-1); + } - _parse_version(sl, &sl->version); + _parse_version(sl, &sl->version); - DLOG("st vid = 0x%04x (expect 0x%04x)\n", sl->version.st_vid, STLINK_USB_VID_ST); - DLOG("stlink pid = 0x%04x\n", sl->version.stlink_pid); - DLOG("stlink version = 0x%x\n", sl->version.stlink_v); - DLOG("jtag version = 0x%x\n", sl->version.jtag_v); - DLOG("swim version = 0x%x\n", sl->version.swim_v); + DLOG("st vid = 0x%04x (expect 0x%04x)\n", sl->version.st_vid, + STLINK_USB_VID_ST); + DLOG("stlink pid = 0x%04x\n", sl->version.stlink_pid); + DLOG("stlink version = 0x%x\n", sl->version.stlink_v); + DLOG("jtag version = 0x%x\n", sl->version.jtag_v); + DLOG("swim version = 0x%x\n", sl->version.swim_v); - if (sl->version.jtag_v == 0) { - DLOG(" notice: the firmware doesn't support a jtag/swd interface\n"); - } + if (sl->version.jtag_v == 0) { + DLOG(" notice: the firmware doesn't support a jtag/swd interface\n"); + } - if (sl->version.swim_v == 0) { - DLOG(" notice: the firmware doesn't support a swim interface\n"); - } + if (sl->version.swim_v == 0) { + DLOG(" notice: the firmware doesn't support a swim interface\n"); + } - return(0); + return (0); } int stlink_target_voltage(stlink_t *sl) { - int voltage = -1; - DLOG("*** reading target voltage\n"); + int voltage = -1; + DLOG("*** reading target voltage\n"); - if (sl->backend->target_voltage != NULL) { - voltage = sl->backend->target_voltage(sl); + if (sl->backend->target_voltage != NULL) { + voltage = sl->backend->target_voltage(sl); - if (voltage != -1) { - DLOG("target voltage = %imV\n", voltage); - } else { - DLOG("error reading target voltage\n"); - } + if (voltage != -1) { + DLOG("target voltage = %imV\n", voltage); } else { - DLOG("reading voltage not supported by backend\n"); + DLOG("error reading target voltage\n"); } + } else { + DLOG("reading voltage not supported by backend\n"); + } - return(voltage); + return (voltage); } int stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { - int ret; + int ret; - ret = sl->backend->read_debug32(sl, addr, data); - if (!ret) - DLOG("*** stlink_read_debug32 %#010x at %#010x\n", *data, addr); + ret = sl->backend->read_debug32(sl, addr, data); + if (!ret) + DLOG("*** stlink_read_debug32 %#010x at %#010x\n", *data, addr); - return(ret); + return (ret); } int stlink_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { - DLOG("*** stlink_write_debug32 %#010x to %#010x\n", data, addr); - return sl->backend->write_debug32(sl, addr, data); + DLOG("*** stlink_write_debug32 %#010x to %#010x\n", data, addr); + return sl->backend->write_debug32(sl, addr, data); } int stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { - DLOG("*** stlink_write_mem32 %u bytes to %#x\n", len, addr); + DLOG("*** stlink_write_mem32 %u bytes to %#x\n", len, addr); - if (len % 4 != 0) { - fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", - len % 4); - abort(); - } + if (len % 4 != 0) { + ELOG("Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4); + return (-1); + } - return(sl->backend->write_mem32(sl, addr, len)); + return (sl->backend->write_mem32(sl, addr, len)); } int stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { - DLOG("*** stlink_read_mem32 ***\n"); + DLOG("*** stlink_read_mem32 ***\n"); - if (len % 4 != 0) { // !!! never ever: fw gives just wrong values - fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", - len % 4); - abort(); - } + if (len % 4 != 0) { // !!! never ever: fw gives just wrong values + ELOG("Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4); + return (-1); + } - return(sl->backend->read_mem32(sl, addr, len)); + return (sl->backend->read_mem32(sl, addr, len)); } int stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { - DLOG("*** stlink_write_mem8 ***\n"); + DLOG("*** stlink_write_mem8 ***\n"); - if (len > 0x40) { // !!! never ever: Writing more then 0x40 bytes gives unexpected behaviour - fprintf(stderr, "Error: Data length > 64: +%d byte.\n", - len); - abort(); - } + if (len > 0x40) { // !!! never ever: Writing more then 0x40 bytes gives + // unexpected behaviour + ELOG("Data length > 64: +%d byte.\n", len); + return (-1); + } - return(sl->backend->write_mem8(sl, addr, len)); + return (sl->backend->write_mem8(sl, addr, len)); } int stlink_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { - DLOG("*** stlink_read_all_regs ***\n"); - return(sl->backend->read_all_regs(sl, regp)); + DLOG("*** stlink_read_all_regs ***\n"); + return (sl->backend->read_all_regs(sl, regp)); } int stlink_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp) { - DLOG("*** stlink_read_all_unsupported_regs ***\n"); - return(sl->backend->read_all_unsupported_regs(sl, regp)); + DLOG("*** stlink_read_all_unsupported_regs ***\n"); + return (sl->backend->read_all_unsupported_regs(sl, regp)); } int stlink_write_reg(stlink_t *sl, uint32_t reg, int idx) { - DLOG("*** stlink_write_reg\n"); - return(sl->backend->write_reg(sl, reg, idx)); + DLOG("*** stlink_write_reg\n"); + return (sl->backend->write_reg(sl, reg, idx)); } int stlink_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { - DLOG("*** stlink_read_reg\n"); - DLOG(" (%d) ***\n", r_idx); + DLOG("*** stlink_read_reg\n"); + DLOG(" (%d) ***\n", r_idx); - if (r_idx > 20 || r_idx < 0) { - fprintf(stderr, "Error: register index must be in [0..20]\n"); - return(-1); - } + if (r_idx > 20 || r_idx < 0) { + fprintf(stderr, "Error: register index must be in [0..20]\n"); + return (-1); + } - return(sl->backend->read_reg(sl, r_idx, regp)); + return (sl->backend->read_reg(sl, r_idx, regp)); } -int stlink_read_unsupported_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { - int r_convert; +int stlink_read_unsupported_reg(stlink_t *sl, int r_idx, + struct stlink_reg *regp) { + int r_convert; - DLOG("*** stlink_read_unsupported_reg\n"); - DLOG(" (%d) ***\n", r_idx); + DLOG("*** stlink_read_unsupported_reg\n"); + DLOG(" (%d) ***\n", r_idx); - /* Convert to values used by STLINK_REG_DCRSR */ - if (r_idx >= 0x1C && r_idx <= 0x1F) { // primask, basepri, faultmask, or control - r_convert = 0x14; - } else if (r_idx == 0x40) { // FPSCR - r_convert = 0x21; - } else if (r_idx >= 0x20 && r_idx < 0x40) { - r_convert = 0x40 + (r_idx - 0x20); - } else { - fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n"); - return(-1); - } + /* Convert to values used by STLINK_REG_DCRSR */ + if (r_idx >= 0x1C && + r_idx <= 0x1F) { // primask, basepri, faultmask, or control + r_convert = 0x14; + } else if (r_idx == 0x40) { // FPSCR + r_convert = 0x21; + } else if (r_idx >= 0x20 && r_idx < 0x40) { + r_convert = 0x40 + (r_idx - 0x20); + } else { + fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n"); + return (-1); + } - return(sl->backend->read_unsupported_reg(sl, r_convert, regp)); + return (sl->backend->read_unsupported_reg(sl, r_convert, regp)); } -int stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, struct stlink_reg *regp) { - int r_convert; +int stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, + struct stlink_reg *regp) { + int r_convert; - DLOG("*** stlink_write_unsupported_reg\n"); - DLOG(" (%d) ***\n", r_idx); + DLOG("*** stlink_write_unsupported_reg\n"); + DLOG(" (%d) ***\n", r_idx); - /* Convert to values used by STLINK_REG_DCRSR */ - if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */ - r_convert = r_idx; // the backend function handles this - } else if (r_idx == 0x40) { // FPSCR - r_convert = 0x21; - } else if (r_idx >= 0x20 && r_idx < 0x40) { - r_convert = 0x40 + (r_idx - 0x20); - } else { - fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n"); - return(-1); - } + /* Convert to values used by STLINK_REG_DCRSR */ + if (r_idx >= 0x1C && + r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */ + r_convert = r_idx; // the backend function handles this + } else if (r_idx == 0x40) { // FPSCR + r_convert = 0x21; + } else if (r_idx >= 0x20 && r_idx < 0x40) { + r_convert = 0x40 + (r_idx - 0x20); + } else { + fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n"); + return (-1); + } - return(sl->backend->write_unsupported_reg(sl, val, r_convert, regp)); + return (sl->backend->write_unsupported_reg(sl, val, r_convert, regp)); } bool stlink_is_core_halted(stlink_t *sl) { - stlink_status(sl); - return(sl->core_stat == TARGET_HALTED); + stlink_status(sl); + return (sl->core_stat == TARGET_HALTED); } int stlink_step(stlink_t *sl) { - DLOG("*** stlink_step ***\n"); - return(sl->backend->step(sl)); + DLOG("*** stlink_step ***\n"); + return (sl->backend->step(sl)); } int stlink_current_mode(stlink_t *sl) { - int mode = sl->backend->current_mode(sl); - - switch (mode) { - case STLINK_DEV_DFU_MODE: - DLOG("stlink current mode: dfu\n"); - return(mode); - case STLINK_DEV_DEBUG_MODE: - DLOG("stlink current mode: debug (jtag or swd)\n"); - return(mode); - case STLINK_DEV_MASS_MODE: - DLOG("stlink current mode: mass\n"); - return(mode); - } + int mode = sl->backend->current_mode(sl); - DLOG("stlink mode: unknown!\n"); - return(STLINK_DEV_UNKNOWN_MODE); -} + switch (mode) { + case STLINK_DEV_DFU_MODE: + DLOG("stlink current mode: dfu\n"); + return (mode); + case STLINK_DEV_DEBUG_MODE: + DLOG("stlink current mode: debug (jtag or swd)\n"); + return (mode); + case STLINK_DEV_MASS_MODE: + DLOG("stlink current mode: mass\n"); + return (mode); + } -int stlink_trace_enable(stlink_t* sl, uint32_t frequency) { - DLOG("*** stlink_trace_enable ***\n"); - return(sl->backend->trace_enable(sl, frequency)); + DLOG("stlink mode: unknown!\n"); + return (STLINK_DEV_UNKNOWN_MODE); } -int stlink_trace_disable(stlink_t* sl) { - DLOG("*** stlink_trace_disable ***\n"); - return(sl->backend->trace_disable(sl)); +int stlink_trace_enable(stlink_t *sl, uint32_t frequency) { + DLOG("*** stlink_trace_enable ***\n"); + return (sl->backend->trace_enable(sl, frequency)); } -int stlink_trace_read(stlink_t* sl, uint8_t* buf, size_t size) { - return(sl->backend->trace_read(sl, buf, size)); +int stlink_trace_disable(stlink_t *sl) { + DLOG("*** stlink_trace_disable ***\n"); + return (sl->backend->trace_disable(sl)); } +int stlink_trace_read(stlink_t *sl, uint8_t *buf, size_t size) { + return (sl->backend->trace_read(sl, buf, size)); +} // End of delegates.... Common code below here... - - -// same as above with entrypoint. +// same as above with entrypoint. void stlink_run_at(stlink_t *sl, stm32_addr_t addr) { - stlink_write_reg(sl, addr, 15); /* pc register */ - stlink_run(sl); + stlink_write_reg(sl, addr, 15); /* pc register */ + stlink_run(sl, RUN_NORMAL); - while (stlink_is_core_halted(sl)) { usleep(3000000); } + while (stlink_is_core_halted(sl)) { + usleep(3000000); + } } - // this function is called by stlink_status() // do not call stlink_core_stat() directly, always use stlink_status() void stlink_core_stat(stlink_t *sl) { - switch (sl->core_stat ) { - case TARGET_RUNNING: - DLOG(" core status: running\n"); - return; - case TARGET_HALTED: - DLOG(" core status: halted\n"); - return; - case TARGET_RESET: - DLOG(" core status: reset\n"); - return; - case TARGET_DEBUG_RUNNING: - DLOG(" core status: debug running\n"); - return; - default: - DLOG(" core status: unknown\n"); - } + switch (sl->core_stat) { + case TARGET_RUNNING: + DLOG(" core status: running\n"); + return; + case TARGET_HALTED: + DLOG(" core status: halted\n"); + return; + case TARGET_RESET: + DLOG(" core status: reset\n"); + return; + case TARGET_DEBUG_RUNNING: + DLOG(" core status: debug running\n"); + return; + default: + DLOG(" core status: unknown\n"); + } } -void stlink_print_data(stlink_t * sl) { - if (sl->q_len <= 0 || sl->verbose < UDEBUG) { return; } +void stlink_print_data(stlink_t *sl) { + if (sl->q_len <= 0 || sl->verbose < UDEBUG) { + return; + } - if (sl->verbose > 2) { DLOG("data_len = %d 0x%x\n", sl->q_len, sl->q_len); } + if (sl->verbose > 2) { + DLOG("data_len = %d 0x%x\n", sl->q_len, sl->q_len); + } - for (int i = 0; i < sl->q_len; i++) { - if (i % 16 == 0) { - /* - if (sl->q_data_dir == Q_DATA_OUT) { - fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i); - } else { - fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i); - } - */ - } - //DLOG(" %02x", (unsigned int) sl->q_buf[i]); - fprintf(stderr, " %02x", (unsigned int) sl->q_buf[i]); + for (int i = 0; i < sl->q_len; i++) { + if (i % 16 == 0) { + /* + if (sl->q_data_dir == Q_DATA_OUT) { + fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i); + } else { + fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i); + } + */ } - //DLOG("\n\n"); - fprintf(stderr, "\n"); + // DLOG(" %02x", (unsigned int) sl->q_buf[i]); + fprintf(stderr, " %02x", (unsigned int)sl->q_buf[i]); + } + // DLOG("\n\n"); + fprintf(stderr, "\n"); } /* Memory mapped file */ typedef struct mapped_file { - uint8_t* base; - size_t len; + uint8_t *base; + size_t len; } mapped_file_t; -#define MAPPED_FILE_INITIALIZER { NULL, 0 } +#define MAPPED_FILE_INITIALIZER \ + { NULL, 0 } -static int map_file(mapped_file_t* mf, const char* path) { - int error = -1; - struct stat st; +static int map_file(mapped_file_t *mf, const char *path) { + int error = -1; + struct stat st; - const int fd = open(path, O_RDONLY | O_BINARY); + const int fd = open(path, O_RDONLY | O_BINARY); - if (fd == -1) { - fprintf(stderr, "open(%s) == -1\n", path); - return(-1); - } + if (fd == -1) { + fprintf(stderr, "open(%s) == -1\n", path); + return (-1); + } - if (fstat(fd, &st) == -1) { - fprintf(stderr, "fstat(%s) == -1\n", path); - goto on_error; - } + if (fstat(fd, &st) == -1) { + fprintf(stderr, "fstat(%s) == -1\n", path); + goto on_error; + } - if (sizeof(st.st_size) != sizeof(size_t)) { - // on 32 bit systems, check if there is an overflow - if (st.st_size > (off_t)INT32_MAX) { - fprintf(stderr, "mmap() size_t overflow for file %s\n", path); - goto on_error; - } + if (sizeof(st.st_size) != sizeof(size_t)) { + // on 32 bit systems, check if there is an overflow + if (st.st_size > (off_t)INT32_MAX) { + fprintf(stderr, "mmap() size_t overflow for file %s\n", path); + goto on_error; } + } - mf->base = (uint8_t*)mmap(NULL, (size_t)(st.st_size), PROT_READ, MAP_SHARED, fd, 0); + mf->base = + (uint8_t *)mmap(NULL, (size_t)(st.st_size), PROT_READ, MAP_SHARED, fd, 0); - if (mf->base == MAP_FAILED) { - fprintf(stderr, "mmap() == MAP_FAILED for file %s\n", path); - goto on_error; - } + if (mf->base == MAP_FAILED) { + fprintf(stderr, "mmap() == MAP_FAILED for file %s\n", path); + goto on_error; + } - mf->len = st.st_size; - error = 0; // success + mf->len = st.st_size; + error = 0; // success on_error: - close(fd); - return(error); + close(fd); + return (error); } -static void unmap_file(mapped_file_t * mf) { - munmap((void*)mf->base, mf->len); - mf->base = (unsigned char*)MAP_FAILED; - mf->len = 0; +static void unmap_file(mapped_file_t *mf) { + munmap((void *)mf->base, mf->len); + mf->base = (unsigned char *)MAP_FAILED; + mf->len = 0; } -/* Limit the block size to compare to 0x1800 as anything larger will stall the STLINK2 - * Maybe STLINK V1 needs smaller value! +/* Limit the block size to compare to 0x1800 as anything larger will stall the + * STLINK2 Maybe STLINK V1 needs smaller value! */ -static int check_file(stlink_t* sl, mapped_file_t* mf, stm32_addr_t addr) { - size_t off; - size_t n_cmp = sl->flash_pgsz; +static int check_file(stlink_t *sl, mapped_file_t *mf, stm32_addr_t addr) { + size_t off; + size_t n_cmp = sl->flash_pgsz; - if ( n_cmp > 0x1800) { n_cmp = 0x1800; } + if (n_cmp > 0x1800) { + n_cmp = 0x1800; + } - for (off = 0; off < mf->len; off += n_cmp) { - size_t aligned_size; + for (off = 0; off < mf->len; off += n_cmp) { + size_t aligned_size; - size_t cmp_size = n_cmp; // adjust last page size + size_t cmp_size = n_cmp; // adjust last page size - if ((off + n_cmp) > mf->len) { cmp_size = mf->len - off; } + if ((off + n_cmp) > mf->len) { + cmp_size = mf->len - off; + } - aligned_size = cmp_size; + aligned_size = cmp_size; - if (aligned_size & (4 - 1)) { aligned_size = (cmp_size + 4) & ~(4 - 1); } + if (aligned_size & (4 - 1)) { + aligned_size = (cmp_size + 4) & ~(4 - 1); + } - stlink_read_mem32(sl, addr + (uint32_t)off, aligned_size); + stlink_read_mem32(sl, addr + (uint32_t)off, aligned_size); - if (memcmp(sl->q_buf, mf->base + off, cmp_size)) { return(-1); } + if (memcmp(sl->q_buf, mf->base + off, cmp_size)) { + return (-1); } + } - return(0); + return (0); } static void md5_calculate(mapped_file_t *mf) { - // calculate md5 checksum of given binary file - Md5Context md5Context; - MD5_HASH md5Hash; - Md5Initialise(&md5Context); - Md5Update(&md5Context, mf->base, (uint32_t)mf->len); - Md5Finalise(&md5Context, &md5Hash); - printf("md5 checksum: "); + // calculate md5 checksum of given binary file + Md5Context md5Context; + MD5_HASH md5Hash; + Md5Initialise(&md5Context); + Md5Update(&md5Context, mf->base, (uint32_t)mf->len); + Md5Finalise(&md5Context, &md5Hash); + printf("md5 checksum: "); - for (int i = 0; i < (int)sizeof(md5Hash); i++) { printf("%x", md5Hash.bytes[i]); } + for (int i = 0; i < (int)sizeof(md5Hash); i++) { + printf("%x", md5Hash.bytes[i]); + } - printf(", "); + printf(", "); } static void stlink_checksum(mapped_file_t *mp) { - /* checksum that backward compatible with official ST tools */ - uint32_t sum = 0; - uint8_t *mp_byte = (uint8_t *)mp->base; + /* checksum that backward compatible with official ST tools */ + uint32_t sum = 0; + uint8_t *mp_byte = (uint8_t *)mp->base; - for (size_t i = 0; i < mp->len; ++i) { sum += mp_byte[i]; } + for (size_t i = 0; i < mp->len; ++i) { + sum += mp_byte[i]; + } - printf("stlink checksum: 0x%08x\n", sum); + printf("stlink checksum: 0x%08x\n", sum); } static void stlink_fwrite_finalize(stlink_t *sl, stm32_addr_t addr) { - unsigned int val; - // set stack - stlink_read_debug32(sl, addr, &val); - stlink_write_reg(sl, val, 13); - // set PC to the reset routine - stlink_read_debug32(sl, addr + 4, &val); - stlink_write_reg(sl, val, 15); - stlink_run(sl); -} - -int stlink_mwrite_sram(stlink_t * sl, uint8_t* data, uint32_t length, stm32_addr_t addr) { - // write the file in sram at addr - - int error = -1; - size_t off; - size_t len; - - // check addr range is inside the sram - if (addr < sl->sram_base) { - fprintf(stderr, "addr too low\n"); - goto on_error; - } else if ((addr + length) < addr) { - fprintf(stderr, "addr overruns\n"); - goto on_error; - } else if ((addr + length) > (sl->sram_base + sl->sram_size)) { - fprintf(stderr, "addr too high\n"); - goto on_error; - } else if (addr & 3) { - fprintf(stderr, "unaligned addr\n"); - goto on_error; - } - - len = length; - - if (len & 3) { len -= len & 3; } - - // do the copy by 1kB blocks - for (off = 0; off < len; off += 1024) { - size_t size = 1024; - - if ((off + size) > len) { size = len - off; } - - memcpy(sl->q_buf, data + off, size); - - if (size & 3) { size += 2; } // round size if needed - - stlink_write_mem32(sl, addr + (uint32_t)off, size); - } - - if (length > len) { - memcpy(sl->q_buf, data + len, length - len); - stlink_write_mem8(sl, addr + (uint32_t)len, length - len); - } - - - error = 0; // success - stlink_fwrite_finalize(sl, addr); + unsigned int val; + // set stack + stlink_read_debug32(sl, addr, &val); + stlink_write_reg(sl, val, 13); + // set PC to the reset routine + stlink_read_debug32(sl, addr + 4, &val); + stlink_write_reg(sl, val, 15); + stlink_run(sl, RUN_NORMAL); +} + +int stlink_mwrite_sram(stlink_t *sl, uint8_t *data, uint32_t length, + stm32_addr_t addr) { + // write the file in sram at addr + + int error = -1; + size_t off; + size_t len; + + // check addr range is inside the sram + if (addr < sl->sram_base) { + fprintf(stderr, "addr too low\n"); + goto on_error; + } else if ((addr + length) < addr) { + fprintf(stderr, "addr overruns\n"); + goto on_error; + } else if ((addr + length) > (sl->sram_base + sl->sram_size)) { + fprintf(stderr, "addr too high\n"); + goto on_error; + } else if (addr & 3) { + fprintf(stderr, "unaligned addr\n"); + goto on_error; + } + + len = length; + + if (len & 3) { + len -= len & 3; + } + + // do the copy by 1kB blocks + for (off = 0; off < len; off += 1024) { + size_t size = 1024; + + if ((off + size) > len) { + size = len - off; + } + + memcpy(sl->q_buf, data + off, size); + + if (size & 3) { + size += 2; + } // round size if needed + + stlink_write_mem32(sl, addr + (uint32_t)off, size); + } + + if (length > len) { + memcpy(sl->q_buf, data + len, length - len); + stlink_write_mem8(sl, addr + (uint32_t)len, length - len); + } + + error = 0; // success + stlink_fwrite_finalize(sl, addr); on_error: - return(error); + return (error); } -int stlink_fwrite_sram(stlink_t * sl, const char* path, stm32_addr_t addr) { - // write the file in sram at addr +int stlink_fwrite_sram(stlink_t *sl, const char *path, stm32_addr_t addr) { + // write the file in sram at addr - int error = -1; - size_t off; - size_t len; - mapped_file_t mf = MAPPED_FILE_INITIALIZER; + int error = -1; + size_t off; + size_t len; + mapped_file_t mf = MAPPED_FILE_INITIALIZER; - if (map_file(&mf, path) == -1) { - fprintf(stderr, "map_file() == -1\n"); - return(-1); - } + if (map_file(&mf, path) == -1) { + fprintf(stderr, "map_file() == -1\n"); + return (-1); + } - printf("file %s ", path); - md5_calculate(&mf); - stlink_checksum(&mf); - - // check if addr range is inside the SRAM - if (addr < sl->sram_base) { - fprintf(stderr, "addr too low\n"); - goto on_error; - } else if ((addr + mf.len) < addr) { - fprintf(stderr, "addr overruns\n"); - goto on_error; - } else if ((addr + mf.len) > (sl->sram_base + sl->sram_size)) { - fprintf(stderr, "addr too high\n"); - goto on_error; - } else if (addr & 3) { - fprintf(stderr, "unaligned addr\n"); - goto on_error; - } + printf("file %s ", path); + md5_calculate(&mf); + stlink_checksum(&mf); - len = mf.len; + // check if addr range is inside the SRAM + if (addr < sl->sram_base) { + fprintf(stderr, "addr too low\n"); + goto on_error; + } else if ((addr + mf.len) < addr) { + fprintf(stderr, "addr overruns\n"); + goto on_error; + } else if ((addr + mf.len) > (sl->sram_base + sl->sram_size)) { + fprintf(stderr, "addr too high\n"); + goto on_error; + } else if (addr & 3) { + fprintf(stderr, "unaligned addr\n"); + goto on_error; + } - if (len & 3) { len -= len & 3; } + len = mf.len; - // do the copy by 1kB blocks - for (off = 0; off < len; off += 1024) { - size_t size = 1024; + if (len & 3) { + len -= len & 3; + } - if ((off + size) > len) { size = len - off; } + // do the copy by 1kB blocks + for (off = 0; off < len; off += 1024) { + size_t size = 1024; - memcpy(sl->q_buf, mf.base + off, size); + if ((off + size) > len) { + size = len - off; + } - if (size & 3) { size += 2; } // round size if needed + memcpy(sl->q_buf, mf.base + off, size); - stlink_write_mem32(sl, addr + (uint32_t)off, size); - } + if (size & 3) { + size += 2; + } // round size if needed - if (mf.len > len) { - memcpy(sl->q_buf, mf.base + len, mf.len - len); - stlink_write_mem8(sl, addr + (uint32_t)len, mf.len - len); - } + stlink_write_mem32(sl, addr + (uint32_t)off, size); + } - // check the file has been written - if (check_file(sl, &mf, addr) == -1) { - fprintf(stderr, "check_file() == -1\n"); - goto on_error; - } + if (mf.len > len) { + memcpy(sl->q_buf, mf.base + len, mf.len - len); + stlink_write_mem8(sl, addr + (uint32_t)len, mf.len - len); + } + + // check the file has been written + if (check_file(sl, &mf, addr) == -1) { + fprintf(stderr, "check_file() == -1\n"); + goto on_error; + } - error = 0; // success - stlink_fwrite_finalize(sl, addr); + error = 0; // success + stlink_fwrite_finalize(sl, addr); on_error: - unmap_file(&mf); - return(error); + unmap_file(&mf); + return (error); } -typedef bool (*save_block_fn)(void* arg, uint8_t* block, ssize_t len); +typedef bool (*save_block_fn)(void *arg, uint8_t *block, ssize_t len); -static int stlink_read( - stlink_t* sl, stm32_addr_t addr, size_t size, save_block_fn fn, void* fn_arg) { +static int stlink_read(stlink_t *sl, stm32_addr_t addr, size_t size, + save_block_fn fn, void *fn_arg) { - int error = -1; + int error = -1; - if (size < 1) { size = sl->flash_size; } + if (size < 1) { + size = sl->flash_size; + } - if (size > sl->flash_size) { - size = sl->flash_size; - } + if (size > sl->flash_size) { + size = sl->flash_size; + } - size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz; + size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz; - for (size_t off = 0; off < size; off += cmp_size) { - size_t aligned_size; + for (size_t off = 0; off < size; off += cmp_size) { + size_t aligned_size; - // adjust last page size - if ((off + cmp_size) > size) { cmp_size = size - off; } + // adjust last page size + if ((off + cmp_size) > size) { + cmp_size = size - off; + } - aligned_size = cmp_size; + aligned_size = cmp_size; - if (aligned_size & (4 - 1)) { aligned_size = (cmp_size + 4) & ~(4 - 1); } + if (aligned_size & (4 - 1)) { + aligned_size = (cmp_size + 4) & ~(4 - 1); + } - stlink_read_mem32(sl, addr + (uint32_t)off, aligned_size); + stlink_read_mem32(sl, addr + (uint32_t)off, aligned_size); - if (!fn(fn_arg, sl->q_buf, aligned_size)) { goto on_error; } + if (!fn(fn_arg, sl->q_buf, aligned_size)) { + goto on_error; } + } - error = 0; // success + error = 0; // success on_error: - return(error); + return (error); } struct stlink_fread_worker_arg { - int fd; + int fd; }; -static bool stlink_fread_worker(void* arg, uint8_t* block, ssize_t len) { - struct stlink_fread_worker_arg* the_arg = (struct stlink_fread_worker_arg*)arg; +static bool stlink_fread_worker(void *arg, uint8_t *block, ssize_t len) { + struct stlink_fread_worker_arg *the_arg = + (struct stlink_fread_worker_arg *)arg; - if (write(the_arg->fd, block, len) != len) { - fprintf(stderr, "write() != aligned_size\n"); - return(false); - } else { - return(true); - } + if (write(the_arg->fd, block, len) != len) { + fprintf(stderr, "write() != aligned_size\n"); + return (false); + } else { + return (true); + } } struct stlink_fread_ihex_worker_arg { - FILE* file; - uint32_t addr; - uint32_t lba; - uint8_t buf[16]; - uint8_t buf_pos; + FILE *file; + uint32_t addr; + uint32_t lba; + uint8_t buf[16]; + uint8_t buf_pos; }; -static bool stlink_fread_ihex_newsegment(struct stlink_fread_ihex_worker_arg* the_arg) { - uint32_t addr = the_arg->addr; - uint8_t sum = 2 + 4 + (uint8_t)((addr & 0xFF000000) >> 24) + (uint8_t)((addr & 0x00FF0000) >> 16); +static bool +stlink_fread_ihex_newsegment(struct stlink_fread_ihex_worker_arg *the_arg) { + uint32_t addr = the_arg->addr; + uint8_t sum = 2 + 4 + (uint8_t)((addr & 0xFF000000) >> 24) + + (uint8_t)((addr & 0x00FF0000) >> 16); - if (17 != fprintf(the_arg->file, ":02000004%04X%02X\r\n", (addr & 0xFFFF0000) >> 16, - (uint8_t)(0x100 - sum))) { - return(false); - } + if (17 != fprintf(the_arg->file, ":02000004%04X%02X\r\n", + (addr & 0xFFFF0000) >> 16, (uint8_t)(0x100 - sum))) { + return (false); + } - the_arg->lba = (addr & 0xFFFF0000); - return(true); + the_arg->lba = (addr & 0xFFFF0000); + return (true); } -static bool stlink_fread_ihex_writeline(struct stlink_fread_ihex_worker_arg* the_arg) { - uint8_t count = the_arg->buf_pos; +static bool +stlink_fread_ihex_writeline(struct stlink_fread_ihex_worker_arg *the_arg) { + uint8_t count = the_arg->buf_pos; - if (count == 0) { return(true); } + if (count == 0) { + return (true); + } - uint32_t addr = the_arg->addr; + uint32_t addr = the_arg->addr; - if (the_arg->lba != (addr & 0xFFFF0000)) { // segment changed - if (!stlink_fread_ihex_newsegment(the_arg)) { - return(false); - } + if (the_arg->lba != (addr & 0xFFFF0000)) { // segment changed + if (!stlink_fread_ihex_newsegment(the_arg)) { + return (false); } + } - uint8_t sum = count + (uint8_t)((addr & 0x0000FF00) >> 8) + (uint8_t)(addr & 0x000000FF); + uint8_t sum = count + (uint8_t)((addr & 0x0000FF00) >> 8) + + (uint8_t)(addr & 0x000000FF); - if (9 != fprintf(the_arg->file, ":%02X%04X00", count, (addr & 0x0000FFFF))) { - return(false); - } + if (9 != fprintf(the_arg->file, ":%02X%04X00", count, (addr & 0x0000FFFF))) { + return (false); + } - for (uint8_t i = 0; i < count; ++i) { - uint8_t b = the_arg->buf[i]; - sum += b; + for (uint8_t i = 0; i < count; ++i) { + uint8_t b = the_arg->buf[i]; + sum += b; - if (2 != fprintf(the_arg->file, "%02X", b)) { - return(false); - } + if (2 != fprintf(the_arg->file, "%02X", b)) { + return (false); } + } - if (4 != fprintf(the_arg->file, "%02X\r\n", (uint8_t)(0x100 - sum))) { - return(false); - } + if (4 != fprintf(the_arg->file, "%02X\r\n", (uint8_t)(0x100 - sum))) { + return (false); + } - the_arg->addr += count; - the_arg->buf_pos = 0; + the_arg->addr += count; + the_arg->buf_pos = 0; - return(true); + return (true); } -static bool stlink_fread_ihex_init( - struct stlink_fread_ihex_worker_arg* the_arg, int fd, stm32_addr_t addr) { - the_arg->file = fdopen(fd, "w"); - the_arg->addr = addr; - the_arg->lba = 0; - the_arg->buf_pos = 0; +static bool stlink_fread_ihex_init(struct stlink_fread_ihex_worker_arg *the_arg, + int fd, stm32_addr_t addr) { + the_arg->file = fdopen(fd, "w"); + the_arg->addr = addr; + the_arg->lba = 0; + the_arg->buf_pos = 0; - return (the_arg->file != NULL); + return (the_arg->file != NULL); } -static bool stlink_fread_ihex_worker(void* arg, uint8_t* block, ssize_t len) { - struct stlink_fread_ihex_worker_arg* the_arg = (struct stlink_fread_ihex_worker_arg*)arg; - - for (ssize_t i = 0; i < len; ++i) { - if (the_arg->buf_pos == sizeof(the_arg->buf)) { // line is full - if (!stlink_fread_ihex_writeline(the_arg)) { return(false); } - } +static bool stlink_fread_ihex_worker(void *arg, uint8_t *block, ssize_t len) { + struct stlink_fread_ihex_worker_arg *the_arg = + (struct stlink_fread_ihex_worker_arg *)arg; - the_arg->buf[the_arg->buf_pos++] = block[i]; + for (ssize_t i = 0; i < len; ++i) { + if (the_arg->buf_pos == sizeof(the_arg->buf)) { // line is full + if (!stlink_fread_ihex_writeline(the_arg)) { + return (false); + } } - return(true); + the_arg->buf[the_arg->buf_pos++] = block[i]; + } + + return (true); } -static bool stlink_fread_ihex_finalize(struct stlink_fread_ihex_worker_arg* the_arg) { - if (!stlink_fread_ihex_writeline(the_arg)) { return(false); } +static bool +stlink_fread_ihex_finalize(struct stlink_fread_ihex_worker_arg *the_arg) { + if (!stlink_fread_ihex_writeline(the_arg)) { + return (false); + } - // FIXME: do we need the Start Linear Address? + // FIXME: do we need the Start Linear Address? - if (13 != fprintf(the_arg->file, ":00000001FF\r\n")) { // EoF - return(false); - } + if (13 != fprintf(the_arg->file, ":00000001FF\r\n")) { // EoF + return (false); + } - return (0 == fclose(the_arg->file)); + return (0 == fclose(the_arg->file)); } -int stlink_fread(stlink_t* sl, const char* path, bool is_ihex, stm32_addr_t addr, size_t size) { - // read size bytes from addr to file - ILOG("read from address %#010x size %u\n", addr, (unsigned)size); +int stlink_fread(stlink_t *sl, const char *path, bool is_ihex, + stm32_addr_t addr, size_t size) { + // read size bytes from addr to file + ILOG("read from address %#010x size %u\n", addr, (unsigned)size); - int error; - int fd = open(path, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 00700); + int error; + int fd = open(path, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 00700); - if (fd == -1) { - fprintf(stderr, "open(%s) == -1\n", path); - return(-1); - } + if (fd == -1) { + fprintf(stderr, "open(%s) == -1\n", path); + return (-1); + } - if (is_ihex) { - struct stlink_fread_ihex_worker_arg arg; + if (is_ihex) { + struct stlink_fread_ihex_worker_arg arg; - if (stlink_fread_ihex_init(&arg, fd, addr)) { - error = stlink_read(sl, addr, size, &stlink_fread_ihex_worker, &arg); + if (stlink_fread_ihex_init(&arg, fd, addr)) { + error = stlink_read(sl, addr, size, &stlink_fread_ihex_worker, &arg); - if (!stlink_fread_ihex_finalize(&arg)) { error = -1; } - } else { - error = -1; - } + if (!stlink_fread_ihex_finalize(&arg)) { + error = -1; + } } else { - struct stlink_fread_worker_arg arg = { fd }; - error = stlink_read(sl, addr, size, &stlink_fread_worker, &arg); + error = -1; } + } else { + struct stlink_fread_worker_arg arg = {fd}; + error = stlink_read(sl, addr, size, &stlink_fread_worker, &arg); + } - close(fd); - return(error); + close(fd); + return (error); } -int write_buffer_to_sram(stlink_t *sl, flash_loader_t* fl, const uint8_t* buf, size_t size) { - // write the buffer right after the loader - size_t chunk = size & ~0x3; - size_t rem = size & 0x3; +int write_buffer_to_sram(stlink_t *sl, flash_loader_t *fl, const uint8_t *buf, + size_t size) { + // write the buffer right after the loader + size_t chunk = size & ~0x3; + size_t rem = size & 0x3; - if (chunk) { - memcpy(sl->q_buf, buf, chunk); - stlink_write_mem32(sl, fl->buf_addr, chunk); - } + if (chunk) { + memcpy(sl->q_buf, buf, chunk); + stlink_write_mem32(sl, fl->buf_addr, chunk); + } - if (rem) { - memcpy(sl->q_buf, buf + chunk, rem); - stlink_write_mem8(sl, (fl->buf_addr) + (uint32_t)chunk, rem); - } + if (rem) { + memcpy(sl->q_buf, buf + chunk, rem); + stlink_write_mem8(sl, (fl->buf_addr) + (uint32_t)chunk, rem); + } - return(0); + return (0); } uint32_t calculate_F4_sectornum(uint32_t flashaddr) { - uint32_t offset = 0; - flashaddr &= ~STM32_FLASH_BASE; // page now holding the actual flash address - - if (flashaddr >= 0x100000) { - offset = 12; - flashaddr -= 0x100000; - } - - if (flashaddr < 0x4000) { - return (offset + 0); - } else if (flashaddr < 0x8000) { - return(offset + 1); - } else if (flashaddr < 0xc000) { - return(offset + 2); - } else if (flashaddr < 0x10000) { - return(offset + 3); - } else if (flashaddr < 0x20000) { - return(offset + 4); - } else { - return(offset + (flashaddr / 0x20000) + 4); - } - + uint32_t offset = 0; + flashaddr &= ~STM32_FLASH_BASE; // page now holding the actual flash address + + if (flashaddr >= 0x100000) { + offset = 12; + flashaddr -= 0x100000; + } + + if (flashaddr < 0x4000) { + return (offset + 0); + } else if (flashaddr < 0x8000) { + return (offset + 1); + } else if (flashaddr < 0xc000) { + return (offset + 2); + } else if (flashaddr < 0x10000) { + return (offset + 3); + } else if (flashaddr < 0x20000) { + return (offset + 4); + } else { + return (offset + (flashaddr / 0x20000) + 4); + } } uint32_t calculate_F7_sectornum(uint32_t flashaddr) { - flashaddr &= ~STM32_FLASH_BASE; // Page now holding the actual flash address - - if (flashaddr < 0x20000) { - return(flashaddr / 0x8000); - } else if (flashaddr < 0x40000) { - return(4); - } else { - return((flashaddr / 0x40000) + 4); - } + flashaddr &= ~STM32_FLASH_BASE; // Page now holding the actual flash address + if (flashaddr < 0x20000) { + return (flashaddr / 0x8000); + } else if (flashaddr < 0x40000) { + return (4); + } else { + return ((flashaddr / 0x40000) + 4); + } } -uint32_t calculate_H7_sectornum(stlink_t *sl, uint32_t flashaddr, unsigned bank) { - flashaddr &= ~((bank==BANK_1)?STM32_FLASH_BASE:STM32_H7_FLASH_BANK2_BASE); // sector holding the flash address - return(flashaddr / sl->flash_pgsz); +uint32_t calculate_H7_sectornum(stlink_t *sl, uint32_t flashaddr, + unsigned bank) { + flashaddr &= + ~((bank == BANK_1) + ? STM32_FLASH_BASE + : STM32_H7_FLASH_BANK2_BASE); // sector holding the flash address + return (flashaddr / sl->flash_pgsz); } // returns BKER:PNB for the given page address uint32_t calculate_L4_page(stlink_t *sl, uint32_t flashaddr) { - uint32_t bker = 0; - uint32_t flashopt; - stlink_read_debug32(sl, STM32L4_FLASH_OPTR, &flashopt); - flashaddr -= STM32_FLASH_BASE; - - if (sl->chip_id == STLINK_CHIPID_STM32_L4 || - sl->chip_id == STLINK_CHIPID_STM32_L496X || - sl->chip_id == STLINK_CHIPID_STM32_L4RX) { - // this chip use dual banked flash - if (flashopt & (uint32_t)(1lu << STM32L4_FLASH_OPTR_DUALBANK)) { - uint32_t banksize = (uint32_t)sl->flash_size / 2; - - if (flashaddr >= banksize) { - flashaddr -= banksize; - bker = 0x100; - } - } + uint32_t bker = 0; + uint32_t flashopt; + stlink_read_debug32(sl, STM32L4_FLASH_OPTR, &flashopt); + flashaddr -= STM32_FLASH_BASE; + + if (sl->chip_id == STLINK_CHIPID_STM32_L4 || + sl->chip_id == STLINK_CHIPID_STM32_L496X || + sl->chip_id == STLINK_CHIPID_STM32_L4RX) { + // this chip use dual banked flash + if (flashopt & (uint32_t)(1lu << STM32L4_FLASH_OPTR_DUALBANK)) { + uint32_t banksize = (uint32_t)sl->flash_size / 2; + + if (flashaddr >= banksize) { + flashaddr -= banksize; + bker = 0x100; + } } + } - // For 1MB chips without the dual-bank option set, the page address will overflow - // into the BKER bit, which gives us the correct bank:page value. - return(bker | flashaddr / (uint32_t)sl->flash_pgsz); + // For 1MB chips without the dual-bank option set, the page address will + // overflow into the BKER bit, which gives us the correct bank:page value. + return (bker | flashaddr / (uint32_t)sl->flash_pgsz); } uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr) { - if ((sl->chip_id == STLINK_CHIPID_STM32_F2) || - (sl->chip_id == STLINK_CHIPID_STM32_F4) || - (sl->chip_id == STLINK_CHIPID_STM32_F4_DE) || - (sl->chip_id == STLINK_CHIPID_STM32_F4_LP) || - (sl->chip_id == STLINK_CHIPID_STM32_F4_HD) || - (sl->chip_id == STLINK_CHIPID_STM32_F411RE) || - (sl->chip_id == STLINK_CHIPID_STM32_F446) || - (sl->chip_id == STLINK_CHIPID_STM32_F4_DSI) || - (sl->chip_id == STLINK_CHIPID_STM32_F72XXX) || - (sl->chip_id == STLINK_CHIPID_STM32_F412)) { - uint32_t sector = calculate_F4_sectornum(flashaddr); - - if (sector >= 12) { sector -= 12; } - - if (sector < 4) { - sl->flash_pgsz = 0x4000; - } else if (sector < 5) { - sl->flash_pgsz = 0x10000; - } else { - sl->flash_pgsz = 0x20000; - } - } else if (sl->chip_id == STLINK_CHIPID_STM32_F7 || - sl->chip_id == STLINK_CHIPID_STM32_F7XXXX) { - uint32_t sector = calculate_F7_sectornum(flashaddr); + if ((sl->chip_id == STLINK_CHIPID_STM32_F2) || + (sl->chip_id == STLINK_CHIPID_STM32_F4) || + (sl->chip_id == STLINK_CHIPID_STM32_F4_DE) || + (sl->chip_id == STLINK_CHIPID_STM32_F4_LP) || + (sl->chip_id == STLINK_CHIPID_STM32_F4_HD) || + (sl->chip_id == STLINK_CHIPID_STM32_F411RE) || + (sl->chip_id == STLINK_CHIPID_STM32_F446) || + (sl->chip_id == STLINK_CHIPID_STM32_F4_DSI) || + (sl->chip_id == STLINK_CHIPID_STM32_F72XXX) || + (sl->chip_id == STLINK_CHIPID_STM32_F412)) { + uint32_t sector = calculate_F4_sectornum(flashaddr); + + if (sector >= 12) { + sector -= 12; + } + + if (sector < 4) { + sl->flash_pgsz = 0x4000; + } else if (sector < 5) { + sl->flash_pgsz = 0x10000; + } else { + sl->flash_pgsz = 0x20000; + } + } else if (sl->chip_id == STLINK_CHIPID_STM32_F7 || + sl->chip_id == STLINK_CHIPID_STM32_F7XXXX) { + uint32_t sector = calculate_F7_sectornum(flashaddr); - if (sector < 4) { - sl->flash_pgsz = 0x8000; - } else if (sector < 5) { - sl->flash_pgsz = 0x20000; - } else { - sl->flash_pgsz = 0x40000; - } + if (sector < 4) { + sl->flash_pgsz = 0x8000; + } else if (sector < 5) { + sl->flash_pgsz = 0x20000; + } else { + sl->flash_pgsz = 0x40000; } + } - return((uint32_t)sl->flash_pgsz); + return ((uint32_t)sl->flash_pgsz); } /** - * Erase a page of flash, assumes sl is fully populated with things like chip/core ids + * Erase a page of flash, assumes sl is fully populated with things like + * chip/core ids * @param sl stlink context * @param flashaddr an address in the flash page to erase * @return 0 on success -ve on failure */ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) { - if (sl->flash_type == STLINK_FLASH_TYPE_F4 || - sl->flash_type == STLINK_FLASH_TYPE_F7 || - sl->flash_type == STLINK_FLASH_TYPE_L4) { - // wait for ongoing op to finish - wait_flash_busy(sl); - - // unlock if locked - unlock_flash_if(sl); - - // select the page to erase - if ((sl->chip_id == STLINK_CHIPID_STM32_L4) || - (sl->chip_id == STLINK_CHIPID_STM32_L43X) || - (sl->chip_id == STLINK_CHIPID_STM32_L46X) || - (sl->chip_id == STLINK_CHIPID_STM32_L496X) || - (sl->chip_id == STLINK_CHIPID_STM32_L4RX)) { - // calculate the actual bank+page from the address - uint32_t page = calculate_L4_page(sl, flashaddr); - - fprintf(stderr, "EraseFlash - Page:0x%x Size:0x%x ", - page, stlink_calculate_pagesize(sl, flashaddr)); - - write_flash_cr_bker_pnb(sl, page); - } else if (sl->chip_id == STLINK_CHIPID_STM32_F7 || - sl->chip_id == STLINK_CHIPID_STM32_F7XXXX) { - // calculate the actual page from the address - uint32_t sector = calculate_F7_sectornum(flashaddr); - - fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", - sector, stlink_calculate_pagesize(sl, flashaddr)); - write_flash_cr_snb(sl, sector, BANK_1); - } else { - // calculate the actual page from the address - uint32_t sector = calculate_F4_sectornum(flashaddr); + // wait for ongoing op to finish + wait_flash_busy(sl); + // clear flash IO errors + clear_flash_error(sl); + + if (sl->flash_type == STLINK_FLASH_TYPE_F4 || + sl->flash_type == STLINK_FLASH_TYPE_F7 || + sl->flash_type == STLINK_FLASH_TYPE_L4) { + // unlock if locked + unlock_flash_if(sl); + + // select the page to erase + if ((sl->chip_id == STLINK_CHIPID_STM32_L4) || + (sl->chip_id == STLINK_CHIPID_STM32_L43X) || + (sl->chip_id == STLINK_CHIPID_STM32_L46X) || + (sl->chip_id == STLINK_CHIPID_STM32_L496X) || + (sl->chip_id == STLINK_CHIPID_STM32_L4RX)) { + // calculate the actual bank+page from the address + uint32_t page = calculate_L4_page(sl, flashaddr); + + fprintf(stderr, "EraseFlash - Page:0x%x Size:0x%x ", page, + stlink_calculate_pagesize(sl, flashaddr)); + + write_flash_cr_bker_pnb(sl, page); + } else if (sl->chip_id == STLINK_CHIPID_STM32_F7 || + sl->chip_id == STLINK_CHIPID_STM32_F7XXXX) { + // calculate the actual page from the address + uint32_t sector = calculate_F7_sectornum(flashaddr); - fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", - sector, stlink_calculate_pagesize(sl, flashaddr)); + fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", sector, + stlink_calculate_pagesize(sl, flashaddr)); + write_flash_cr_snb(sl, sector, BANK_1); + } else { + // calculate the actual page from the address + uint32_t sector = calculate_F4_sectornum(flashaddr); - // the SNB values for flash sectors in the second bank do not directly - // follow the values for the first bank on 2mb devices... - if (sector >= 12) { sector += 4; } + fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", sector, + stlink_calculate_pagesize(sl, flashaddr)); - write_flash_cr_snb(sl, sector, BANK_1); - } + // the SNB values for flash sectors in the second bank do not directly + // follow the values for the first bank on 2mb devices... + if (sector >= 12) { + sector += 4; + } + + write_flash_cr_snb(sl, sector, BANK_1); + } - set_flash_cr_strt(sl, BANK_1); // start erase operation - wait_flash_busy(sl); // wait for completion - lock_flash(sl); // TODO: fails to program if this is in + set_flash_cr_strt(sl, BANK_1); // start erase operation + wait_flash_busy(sl); // wait for completion + lock_flash(sl); // TODO: fails to program if this is in #if DEBUG_FLASH - fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl, BANK_1)); + fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl, BANK_1)); #endif - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - uint32_t val; - uint32_t flash_regs_base; + uint32_t val; + uint32_t flash_regs_base = get_stm32l0_flash_base(sl); - if (sl->chip_id == STLINK_CHIPID_STM32_L0 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || - sl->chip_id == STLINK_CHIPID_STM32_L011) { - flash_regs_base = STM32L0_FLASH_REGS_ADDR; - } else { - flash_regs_base = STM32L_FLASH_REGS_ADDR; - } + // check if the locks are set + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - // check if the locks are set - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if ((val & (1 << 0)) || (val & (1 << 1))) { + // disable pecr protection + stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, + FLASH_L0_PEKEY1); + stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, + FLASH_L0_PEKEY2); - if ((val & (1 << 0)) || (val & (1 << 1))) { - // disable pecr protection - stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY1); - stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY2); + // check pecr.pelock is cleared + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - // check pecr.pelock is cleared - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 0)) { + WLOG("pecr.pelock not clear (%#x)\n", val); + return (-1); + } - if (val & (1 << 0)) { - WLOG("pecr.pelock not clear (%#x)\n", val); - return(-1); - } + // unlock program memory + stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, + FLASH_L0_PRGKEY1); + stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, + FLASH_L0_PRGKEY2); - // unlock program memory - stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY1); - stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY2); + // check pecr.prglock is cleared + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - // check pecr.prglock is cleared - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 1)) { + WLOG("pecr.prglock not clear (%#x)\n", val); + return (-1); + } + } - if (val & (1 << 1)) { - WLOG("pecr.prglock not clear (%#x)\n", val); - return(-1); - } - } + // set pecr.{erase,prog} + val |= (1 << 9) | (1 << 3); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - // set pecr.{erase,prog} - val |= (1 << 9) | (1 << 3); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); -#if 0 - /* Wait for sr.busy to be cleared - * MP: Test shows that busy bit is not set here. Perhaps, PM0062 is wrong - * and we do not need to wait here for clearing the busy bit. - */ - do { - stlink_read_debug32(sl, STM32L_FLASH_SR, &val) - } while ((val & (1 << 0)) != 0); -#endif + // write 0 to the first word of the page to be erased + stlink_write_debug32(sl, flashaddr, 0); - // write 0 to the first word of the page to be erased - stlink_write_debug32(sl, flashaddr, 0); - - /* MP: It is better to wait for clearing the busy bit after issuing page - * erase command, even though PM0062 recommends to wait before it. - * Test shows that a few iterations is performed in the following loop - * before busy bit is cleared. - */ - do - stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); - while ((val & (1 << 0)) != 0); - - // reset lock bits - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - val |= (1 << 0) | (1 << 1) | (1 << 2); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || - sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - uint32_t val; - wait_flash_busy(sl); // wait for any ongoing Flash operation to finish - unlock_flash_if(sl); - set_flash_cr_per(sl, BANK_1); // set the 'enable Flash erase' bit - - // set the page to erase - if (sl->flash_type == STLINK_FLASH_TYPE_WB) { - uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); - stlink_read_debug32(sl, STM32WB_FLASH_CR, &val); - - // sec 3.10.5 - PNB[7:0] is offset by 3. - val &= ~(0xFF << 3); // Clear previously set page number (if any) - val |= ((flash_page & 0xFF) << 3); - - stlink_write_debug32(sl, STM32WB_FLASH_CR, val); - } else if (sl->flash_type == STLINK_FLASH_TYPE_G0) { - uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); - stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); - // sec 3.7.5 - PNB[5:0] is offset by 3. PER is 0x2. - val &= ~(0x3F << 3); - val |= ((flash_page & 0x3F) << 3) | (1 << FLASH_CR_PER); - stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); - } else if (sl->flash_type == STLINK_FLASH_TYPE_G4) { - uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); - stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); - // sec 3.7.5 - PNB[6:0] is offset by 3. PER is 0x2. - val &= ~(0x7F << 3); - val |= ((flash_page & 0x7F) << 3) | (1 << FLASH_CR_PER); - stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); - } + /* MP: It is better to wait for clearing the busy bit after issuing page + * erase command, even though PM0062 recommends to wait before it. + * Test shows that a few iterations is performed in the following loop + * before busy bit is cleared. + */ + wait_flash_busy(sl); - set_flash_cr_strt(sl, BANK_1); // set the 'start operation' bit - wait_flash_busy(sl); // wait for the 'busy' bit to clear - clear_flash_cr_per(sl, BANK_1); // clear the 'enable page erase' bit - lock_flash(sl); - } else if (sl->flash_type == STLINK_FLASH_TYPE_F0 || - sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { - unsigned bank = (flashaddr < STM32_F1_FLASH_BANK2_BASE)?BANK_1:BANK_2; - wait_flash_busy(sl); - unlock_flash_if(sl); - clear_flash_cr_pg(sl, bank); // clear the pg bit - set_flash_cr_per(sl, bank); // set the page erase bit - write_flash_ar(sl, flashaddr, bank); // select the page to erase - set_flash_cr_strt(sl, bank); // start erase operation, reset by hw with busy bit - wait_flash_busy(sl); - lock_flash(sl); - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - unsigned bank = (flashaddr < STM32_H7_FLASH_BANK2_BASE)?BANK_1:BANK_2; - wait_flash_busy(sl); // wait for ongoing op to finish - unlock_flash_if(sl); // unlock if locked - uint32_t sector = calculate_H7_sectornum(sl, flashaddr, bank);// calculate the actual page from the address - write_flash_cr_snb(sl, sector, bank); // select the page to erase - set_flash_cr_strt(sl, bank); // start erase operation - wait_flash_busy(sl); // wait for completion - lock_flash(sl); - } else { - WLOG("unknown coreid %x, page erase failed\n", sl->core_id); - return(-1); - } + // reset lock bits + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + val |= (1 << 0) | (1 << 1) | (1 << 2); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || + sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + uint32_t val; + unlock_flash_if(sl); + set_flash_cr_per(sl, BANK_1); // set the 'enable Flash erase' bit + + // set the page to erase + if (sl->flash_type == STLINK_FLASH_TYPE_WB) { + uint32_t flash_page = + ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); + stlink_read_debug32(sl, STM32WB_FLASH_CR, &val); + + // sec 3.10.5 - PNB[7:0] is offset by 3. + val &= ~(0xFF << 3); // Clear previously set page number (if any) + val |= ((flash_page & 0xFF) << 3); + + stlink_write_debug32(sl, STM32WB_FLASH_CR, val); + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0) { + uint32_t flash_page = + ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); + stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); + // sec 3.7.5 - PNB[5:0] is offset by 3. PER is 0x2. + val &= ~(0x3F << 3); + val |= ((flash_page & 0x3F) << 3) | (1 << FLASH_CR_PER); + stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); + } else if (sl->flash_type == STLINK_FLASH_TYPE_G4) { + uint32_t flash_page = + ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); + stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); + // sec 3.7.5 - PNB[6:0] is offset by 3. PER is 0x2. + val &= ~(0x7F << 3); + val |= ((flash_page & 0x7F) << 3) | (1 << FLASH_CR_PER); + stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); + } + + set_flash_cr_strt(sl, BANK_1); // set the 'start operation' bit + wait_flash_busy(sl); // wait for the 'busy' bit to clear + clear_flash_cr_per(sl, BANK_1); // clear the 'enable page erase' bit + lock_flash(sl); + } else if (sl->flash_type == STLINK_FLASH_TYPE_F0 || + sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + unsigned bank = (flashaddr < STM32_F1_FLASH_BANK2_BASE) ? BANK_1 : BANK_2; + unlock_flash_if(sl); + clear_flash_cr_pg(sl, bank); // clear the pg bit + set_flash_cr_per(sl, bank); // set the page erase bit + write_flash_ar(sl, flashaddr, bank); // select the page to erase + set_flash_cr_strt(sl, + bank); // start erase operation, reset by hw with busy bit + wait_flash_busy(sl); + clear_flash_cr_per(sl, bank); // clear the page erase bit + lock_flash(sl); + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + unsigned bank = (flashaddr < STM32_H7_FLASH_BANK2_BASE) ? BANK_1 : BANK_2; + unlock_flash_if(sl); // unlock if locked + uint32_t sector = calculate_H7_sectornum( + sl, flashaddr, bank); // calculate the actual page from the address + write_flash_cr_snb(sl, sector, bank); // select the page to erase + set_flash_cr_strt(sl, bank); // start erase operation + wait_flash_busy(sl); // wait for completion + lock_flash(sl); + } else { + WLOG("unknown coreid %x, page erase failed\n", sl->core_id); + return (-1); + } - // TODO: verify the erased page - return(0); + return check_flash_error(sl); } int stlink_erase_flash_mass(stlink_t *sl) { - int err = 0; + int err = 0; - // TODO: User MER bit to mass-erase WB series. - if (sl->flash_type == STLINK_FLASH_TYPE_L0 || - sl->flash_type == STLINK_FLASH_TYPE_WB) { - // erase each page - int i = 0, num_pages = (int)(sl->flash_size / sl->flash_pgsz); + // TODO: User MER bit to mass-erase WB series. + if (sl->flash_type == STLINK_FLASH_TYPE_L0 || + sl->flash_type == STLINK_FLASH_TYPE_WB) { + // erase each page + int i = 0, num_pages = (int)(sl->flash_size / sl->flash_pgsz); - for (i = 0; i < num_pages; i++) { - // addr must be an addr inside the page - stm32_addr_t addr = (stm32_addr_t)sl->flash_base + i * (stm32_addr_t)sl->flash_pgsz; + for (i = 0; i < num_pages; i++) { + // addr must be an addr inside the page + stm32_addr_t addr = + (stm32_addr_t)sl->flash_base + i * (stm32_addr_t)sl->flash_pgsz; - if (stlink_erase_flash_page(sl, addr) == -1) { - WLOG("Failed to erase_flash_page(%#x) == -1\n", addr); - return(-1); - } + if (stlink_erase_flash_page(sl, addr)) { + WLOG("Failed to erase_flash_page(%#x) == -1\n", addr); + return (-1); + } - fprintf(stdout, "-> Flash page at %5d/%5d erased\n", i, num_pages); - fflush(stdout); - } + fprintf(stdout, "-> Flash page at %5d/%5d erased\n", i, num_pages); + fflush(stdout); + } - fprintf(stdout, "\n"); - } else { - wait_flash_busy(sl); - unlock_flash_if(sl); - - if (sl->flash_type == STLINK_FLASH_TYPE_H7 && sl->chip_id != STLINK_CHIPID_STM32_H7AX) { - // set parallelism - write_flash_cr_psiz(sl, 3 /*64it*/, BANK_1); - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - write_flash_cr_psiz(sl, 3 /*64bit*/, BANK_2); - } - } + fprintf(stdout, "\n"); + } else { + wait_flash_busy(sl); + clear_flash_error(sl); + unlock_flash_if(sl); - set_flash_cr_mer(sl, 1, BANK_1); // set the mass erase bit - set_flash_cr_strt(sl, BANK_1); // start erase operation, reset by hw with busy bit + if (sl->flash_type == STLINK_FLASH_TYPE_H7 && + sl->chip_id != STLINK_CHIPID_STM32_H7AX) { + // set parallelism + write_flash_cr_psiz(sl, 3 /*64it*/, BANK_1); + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + write_flash_cr_psiz(sl, 3 /*64bit*/, BANK_2); + } + } - if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL || - (sl->flash_type == STLINK_FLASH_TYPE_H7 && sl->chip_flags & CHIP_F_HAS_DUAL_BANK)) { - set_flash_cr_mer(sl, 1, BANK_2); // set the mass erase bit in bank 2 - set_flash_cr_strt(sl, BANK_2); // start erase operation in bank 2 - } + set_flash_cr_mer(sl, 1, BANK_1); // set the mass erase bit + set_flash_cr_strt( + sl, BANK_1); // start erase operation, reset by hw with busy bit - wait_flash_busy_progress(sl); - err = check_flash_error(sl); - lock_flash(sl); + if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL || + (sl->flash_type == STLINK_FLASH_TYPE_H7 && + sl->chip_flags & CHIP_F_HAS_DUAL_BANK)) { + set_flash_cr_mer(sl, 1, BANK_2); // set the mass erase bit in bank 2 + set_flash_cr_strt(sl, BANK_2); // start erase operation in bank 2 + } - // reset the mass erase bit - set_flash_cr_mer(sl, 0, BANK_1); - if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL || - (sl->flash_type == STLINK_FLASH_TYPE_H7 && sl->chip_flags & CHIP_F_HAS_DUAL_BANK)) { - set_flash_cr_mer(sl, 0, BANK_2); - } + wait_flash_busy_progress(sl); + lock_flash(sl); - // TODO: verify the erased memory + // reset the mass erase bit + set_flash_cr_mer(sl, 0, BANK_1); + if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL || + (sl->flash_type == STLINK_FLASH_TYPE_H7 && + sl->chip_flags & CHIP_F_HAS_DUAL_BANK)) { + set_flash_cr_mer(sl, 0, BANK_2); } - return(err); + err = check_flash_error(sl); + } + + return (err); } -int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { - // check the contents of path are at addr +int stlink_fcheck_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { + // check the contents of path are at addr - int res; - mapped_file_t mf = MAPPED_FILE_INITIALIZER; + int res; + mapped_file_t mf = MAPPED_FILE_INITIALIZER; - if (map_file(&mf, path) == -1) { return(-1); } + if (map_file(&mf, path) == -1) { + return (-1); + } - res = check_file(sl, &mf, addr); - unmap_file(&mf); - return(res); + res = check_file(sl, &mf, addr); + unmap_file(&mf); + return (res); } /** @@ -2633,679 +3047,741 @@ int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { * @param length how much * @return 0 for success, -ve for failure */ -int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, unsigned length) { - size_t off; - size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz; - ILOG("Starting verification of write complete\n"); +int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, + unsigned length) { + size_t off; + size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz; + ILOG("Starting verification of write complete\n"); - for (off = 0; off < length; off += cmp_size) { - size_t aligned_size; + for (off = 0; off < length; off += cmp_size) { + size_t aligned_size; - // adjust last page size - if ((off + cmp_size) > length) { cmp_size = length - off; } + // adjust last page size + if ((off + cmp_size) > length) { + cmp_size = length - off; + } - aligned_size = cmp_size; + aligned_size = cmp_size; - if (aligned_size & (4 - 1)) { aligned_size = (cmp_size + 4) & ~(4 - 1); } + if (aligned_size & (4 - 1)) { + aligned_size = (cmp_size + 4) & ~(4 - 1); + } - stlink_read_mem32(sl, address + (uint32_t)off, aligned_size); + stlink_read_mem32(sl, address + (uint32_t)off, aligned_size); - if (memcmp(sl->q_buf, data + off, cmp_size)) { - ELOG("Verification of flash failed at offset: %u\n", (unsigned int)off); - return(-1); - } + if (memcmp(sl->q_buf, data + off, cmp_size)) { + ELOG("Verification of flash failed at offset: %u\n", (unsigned int)off); + return (-1); } + } - ILOG("Flash written and verified! jolly good!\n"); - return(0); - + ILOG("Flash written and verified! jolly good!\n"); + return (0); } -int stm32l1_write_half_pages( - stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len, uint32_t pagesize) { - unsigned int count; - unsigned int num_half_pages = len / pagesize; - uint32_t val; - uint32_t flash_regs_base; - flash_loader_t fl; - - if (sl->chip_id == STLINK_CHIPID_STM32_L0 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || - sl->chip_id == STLINK_CHIPID_STM32_L011) { - flash_regs_base = STM32L0_FLASH_REGS_ADDR; - } else { - flash_regs_base = STM32L_FLASH_REGS_ADDR; - } +int stm32l1_write_half_pages(stlink_t *sl, stm32_addr_t addr, uint8_t *base, + uint32_t len, uint32_t pagesize) { + unsigned int count; + unsigned int num_half_pages = len / pagesize; + uint32_t val; + uint32_t flash_regs_base = get_stm32l0_flash_base(sl); + flash_loader_t fl; - ILOG("Starting Half page flash write for STM32L core id\n"); + ILOG("Starting Half page flash write for STM32L core id\n"); - /* Flash loader initialisation */ - if (stlink_flash_loader_init(sl, &fl) == -1) { - WLOG("stlink_flash_loader_init() == -1\n"); - return(-1); - } + /* Flash loader initialisation */ + if (stlink_flash_loader_init(sl, &fl) == -1) { + WLOG("stlink_flash_loader_init() == -1\n"); + return (-1); + } - // unlock already done - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - val |= (1 << FLASH_L1_FPRG); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + // unlock already done + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + val |= (1 << FLASH_L1_FPRG); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - val |= (1 << FLASH_L1_PROG); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + val |= (1 << FLASH_L1_PROG); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - do { - stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); - } while ((val & (1 << 0)) != 0); - - for (count = 0; count < num_half_pages; count++) { - if (stlink_flash_loader_run( - sl, &fl, addr + count * pagesize, base + count * pagesize, pagesize) == -1) { - WLOG("l1_stlink_flash_loader_run(%#x) failed! == -1\n", addr + count * pagesize); - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - val &= ~((1 << FLASH_L1_FPRG) | (1 << FLASH_L1_PROG)); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - return(-1); - } + wait_flash_busy(sl); - // wait for sr.busy to be cleared - if (sl->verbose >= 1) { - // show progress; writing procedure is slow and previous errors are misleading - fprintf(stdout, "\r%3u/%u halfpages written", count + 1, num_half_pages); - fflush(stdout); - } + for (count = 0; count < num_half_pages; count++) { + if (stlink_flash_loader_run(sl, &fl, addr + count * pagesize, + base + count * pagesize, pagesize) == -1) { + WLOG("l1_stlink_flash_loader_run(%#x) failed! == -1\n", + addr + count * pagesize); + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + val &= ~((1 << FLASH_L1_FPRG) | (1 << FLASH_L1_PROG)); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + return (-1); + } - do { - stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); - } while ((val & (1 << 0)) != 0); + // wait for sr.busy to be cleared + if (sl->verbose >= 1) { + // show progress; writing procedure is slow and previous errors are + // misleading + fprintf(stdout, "\r%3u/%u halfpages written", count + 1, num_half_pages); + fflush(stdout); } - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - val &= ~(1 << FLASH_L1_PROG); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - val &= ~(1 << FLASH_L1_FPRG); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - return(0); + wait_flash_busy(sl); + } + + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + val &= ~(1 << FLASH_L1_PROG); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + val &= ~(1 << FLASH_L1_FPRG); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + return (0); } int stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl) { - if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || - (sl->flash_type == STLINK_FLASH_TYPE_F7) || - (sl->flash_type == STLINK_FLASH_TYPE_L4)) { - ILOG("Starting Flash write for F2/F4/F7/L4\n"); - - // Flash loader initialisation - if (stlink_flash_loader_init(sl, fl) == -1) { - ELOG("stlink_flash_loader_init() == -1\n"); - return(-1); - } - - unlock_flash_if(sl); // first unlock the cr - - int voltage; - if (sl->version.stlink_v == 1) { - WLOG("STLINK V1 cannot read voltage, use default voltage 3.2V\n"); - voltage = 3200; - } else { - voltage = stlink_target_voltage(sl); - } - - if (voltage == -1) { - ELOG("Failed to read Target voltage\n"); - return(-1); - } - if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - // L4 does not have a byte-write mode - if (voltage < 1710) { - ELOG("Target voltage (%d mV) too low for flash writes!\n", voltage); - return(-1); - } - } else { - if (voltage > 2700) { - ILOG("enabling 32-bit flash writes\n"); - write_flash_cr_psiz(sl, 2, BANK_1); - } else { - ILOG("Target voltage (%d mV) too low for 32-bit flash, " - "using 8-bit flash writes\n", voltage); - write_flash_cr_psiz(sl, 0, BANK_1); - } - } - - // set programming mode - set_flash_cr_pg(sl, BANK_1); - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || - sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - ILOG("Starting Flash write for WB/G0/G4\n"); - - wait_flash_busy(sl); - unlock_flash_if(sl); // unlock flash if necessary - set_flash_cr_pg(sl, BANK_1); // set PG 'allow programming' bit - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - ILOG("Starting Flash write for L0\n"); - - uint32_t val; - uint32_t flash_regs_base; - if (sl->chip_id == STLINK_CHIPID_STM32_L0 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || - sl->chip_id == STLINK_CHIPID_STM32_L011) { - flash_regs_base = STM32L0_FLASH_REGS_ADDR; - } else { - flash_regs_base = STM32L_FLASH_REGS_ADDR; - } - - // disable pecr protection - stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY1); - stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY2); - - // check pecr.pelock is cleared - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - if (val & (1 << 0)) { - ELOG("pecr.pelock not clear\n"); - return(-1); - } - - // unlock program memory - stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY1); - stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY2); - - // check pecr.prglock is cleared - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - if (val & (1 << 1)) { - ELOG("pecr.prglock not clear\n"); - return(-1); - } - } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { - ILOG("Starting Flash write for VL/F0/F3/F1_XL\n"); - - // flash loader initialisation - if (stlink_flash_loader_init(sl, fl) == -1) { - ELOG("stlink_flash_loader_init() == -1\n"); - return(-1); - } - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - ILOG("Starting Flash write for H7\n"); - - unlock_flash_if(sl); // unlock the cr - set_flash_cr_pg(sl, BANK_1); // set programming mode - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - set_flash_cr_pg(sl, BANK_2); - } - if (sl->chip_id != STLINK_CHIPID_STM32_H7AX) { - // set parallelism - write_flash_cr_psiz(sl, 3 /*64it*/, BANK_1); - if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - write_flash_cr_psiz(sl, 3 /*64bit*/, BANK_2); - } - } + // According to DDI0419C, Table C1-7 firstly force halt + stlink_write_debug32(sl, STLINK_REG_DHCSR, + STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN | + STLINK_REG_DHCSR_C_HALT); + // and only then disable interrupts + stlink_write_debug32(sl, STLINK_REG_DHCSR, + STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN | + STLINK_REG_DHCSR_C_HALT | + STLINK_REG_DHCSR_C_MASKINTS); + + // disable DMA + set_dma_state(sl, fl, 0); + + // wait for ongoing op to finish + wait_flash_busy(sl); + // Clear errors + clear_flash_error(sl); + + if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || + (sl->flash_type == STLINK_FLASH_TYPE_F7) || + (sl->flash_type == STLINK_FLASH_TYPE_L4)) { + ILOG("Starting Flash write for F2/F4/F7/L4\n"); + + // Flash loader initialisation + if (stlink_flash_loader_init(sl, fl) == -1) { + ELOG("stlink_flash_loader_init() == -1\n"); + return (-1); + } + + unlock_flash_if(sl); // first unlock the cr + + int voltage; + if (sl->version.stlink_v == 1) { + WLOG("STLINK V1 cannot read voltage, use default voltage 3.2V\n"); + voltage = 3200; } else { - ELOG("unknown coreid, not sure how to write: %x\n", sl->core_id); - return(-1); + voltage = stlink_target_voltage(sl); } - return(0); -} - -int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t addr, - uint8_t* base, uint32_t len) { - size_t off; - if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || - (sl->flash_type == STLINK_FLASH_TYPE_F7) || - (sl->flash_type == STLINK_FLASH_TYPE_L4)) { - size_t buf_size = (sl->sram_size > 0x8000) ? 0x8000 : 0x4000; - for (off = 0; off < len;) { - size_t size = len - off > buf_size ? buf_size : len - off; - if (stlink_flash_loader_run(sl, fl, addr + (uint32_t)off, base + off, size) == -1) { - ELOG("stlink_flash_loader_run(%#x) failed! == -1\n", (unsigned)(addr + off)); - return(-1); - } - - off += size; - } - } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || - sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { - DLOG("Starting %3u page write\r\n", (unsigned int)(len / sl->flash_pgsz)); - for (off = 0; off < len; off += sizeof(uint32_t)) { - uint32_t data; - - if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) { - fprintf(stdout, "\r%3u/%3u pages written", - (unsigned int)(off / sl->flash_pgsz), - (unsigned int)(len / sl->flash_pgsz)); - fflush(stdout); - } + if (voltage == -1) { + ELOG("Failed to read Target voltage\n"); + return (-1); + } - write_uint32((unsigned char*)&data, *(uint32_t*)(base + off)); - stlink_write_debug32(sl, addr + (uint32_t)off, data); - wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear - } - fprintf(stdout, "\n"); + if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + // L4 does not have a byte-write mode + if (voltage < 1710) { + ELOG("Target voltage (%d mV) too low for flash writes!\n", voltage); + return (-1); + } + } else { + if (voltage > 2700) { + ILOG("enabling 32-bit flash writes\n"); + write_flash_cr_psiz(sl, 2, BANK_1); + } else { + ILOG("Target voltage (%d mV) too low for 32-bit flash, " + "using 8-bit flash writes\n", + voltage); + write_flash_cr_psiz(sl, 0, BANK_1); + } + } + + // set programming mode + set_flash_cr_pg(sl, BANK_1); + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || + sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + ILOG("Starting Flash write for WB/G0/G4\n"); + + unlock_flash_if(sl); // unlock flash if necessary + set_flash_cr_pg(sl, BANK_1); // set PG 'allow programming' bit + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + ILOG("Starting Flash write for L0\n"); - // flash writes happen as 2 words at a time - if ((off / sizeof(uint32_t)) % 2 != 0) { - stlink_write_debug32(sl, addr + (uint32_t)off, 0); // write a single word of zeros - wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear - } - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - uint32_t val; - uint32_t flash_regs_base; - uint32_t pagesize; - - if (sl->chip_id == STLINK_CHIPID_STM32_L0 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || - sl->chip_id == STLINK_CHIPID_STM32_L011) { - flash_regs_base = STM32L0_FLASH_REGS_ADDR; - pagesize = L0_WRITE_BLOCK_SIZE; - } else { - flash_regs_base = STM32L_FLASH_REGS_ADDR; - pagesize = L1_WRITE_BLOCK_SIZE; - } + uint32_t val; + uint32_t flash_regs_base; + if (sl->chip_id == STLINK_CHIPID_STM32_L0 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || + sl->chip_id == STLINK_CHIPID_STM32_L011) { + flash_regs_base = STM32L0_FLASH_REGS_ADDR; + } else { + flash_regs_base = STM32L_FLASH_REGS_ADDR; + } - off = 0; + // disable pecr protection + stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, + FLASH_L0_PEKEY1); + stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, + FLASH_L0_PEKEY2); - if (len > pagesize) { - if (stm32l1_write_half_pages(sl, addr, base, len, pagesize) == -1) { - // this may happen on a blank device! - WLOG("\nwrite_half_pages failed == -1\n"); - } else { - off = (len / pagesize) * pagesize; - } - } + // check pecr.pelock is cleared + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 0)) { + ELOG("pecr.pelock not clear\n"); + return (-1); + } - // write remaining word in program memory - for ( ; off < len; off += sizeof(uint32_t)) { - uint32_t data; + // unlock program memory + stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, + FLASH_L0_PRGKEY1); + stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, + FLASH_L0_PRGKEY2); - if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) { - fprintf(stdout, "\r%3u/%3u pages written", - (unsigned int)(off / sl->flash_pgsz), - (unsigned int)(len / sl->flash_pgsz)); - fflush(stdout); - } + // check pecr.prglock is cleared + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 1)) { + ELOG("pecr.prglock not clear\n"); + return (-1); + } + } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + ILOG("Starting Flash write for VL/F0/F3/F1_XL\n"); + + // flash loader initialisation + if (stlink_flash_loader_init(sl, fl) == -1) { + ELOG("stlink_flash_loader_init() == -1\n"); + return (-1); + } + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + ILOG("Starting Flash write for H7\n"); + + unlock_flash_if(sl); // unlock the cr + set_flash_cr_pg(sl, BANK_1); // set programming mode + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + set_flash_cr_pg(sl, BANK_2); + } + if (sl->chip_id != STLINK_CHIPID_STM32_H7AX) { + // set parallelism + write_flash_cr_psiz(sl, 3 /*64it*/, BANK_1); + if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + write_flash_cr_psiz(sl, 3 /*64bit*/, BANK_2); + } + } + } else { + ELOG("unknown coreid, not sure how to write: %x\n", sl->core_id); + return (-1); + } + + return (0); +} + +int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, + stm32_addr_t addr, uint8_t *base, uint32_t len) { + size_t off; + if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || + (sl->flash_type == STLINK_FLASH_TYPE_F7) || + (sl->flash_type == STLINK_FLASH_TYPE_L4)) { + size_t buf_size = (sl->sram_size > 0x8000) ? 0x8000 : 0x4000; + for (off = 0; off < len;) { + size_t size = len - off > buf_size ? buf_size : len - off; + if (stlink_flash_loader_run(sl, fl, addr + (uint32_t)off, base + off, + size) == -1) { + ELOG("stlink_flash_loader_run(%#x) failed! == -1\n", + (unsigned)(addr + off)); + check_flash_error(sl); + return (-1); + } + + off += size; + } + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || + sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { + DLOG("Starting %3u page write\r\n", (unsigned int)(len / sl->flash_pgsz)); + for (off = 0; off < len; off += sizeof(uint32_t)) { + uint32_t data; + + if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) { + fprintf(stdout, "\r%3u/%3u pages written", + (unsigned int)(off / sl->flash_pgsz), + (unsigned int)(len / sl->flash_pgsz)); + fflush(stdout); + } + + write_uint32((unsigned char *)&data, *(uint32_t *)(base + off)); + stlink_write_debug32(sl, addr + (uint32_t)off, data); + wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear + } + fprintf(stdout, "\n"); - write_uint32((unsigned char*)&data, *(uint32_t*)(base + off)); - stlink_write_debug32(sl, addr + (uint32_t)off, data); + // flash writes happen as 2 words at a time + if ((off / sizeof(uint32_t)) % 2 != 0) { + stlink_write_debug32(sl, addr + (uint32_t)off, + 0); // write a single word of zeros + wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear + } + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + uint32_t val; + uint32_t flash_regs_base; + uint32_t pagesize; - // wait for sr.busy to be cleared - do { - stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); - } while ((val & (1 << 0)) != 0); + if (sl->chip_id == STLINK_CHIPID_STM32_L0 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || + sl->chip_id == STLINK_CHIPID_STM32_L011) { + flash_regs_base = STM32L0_FLASH_REGS_ADDR; + pagesize = L0_WRITE_BLOCK_SIZE; + } else { + flash_regs_base = STM32L_FLASH_REGS_ADDR; + pagesize = L1_WRITE_BLOCK_SIZE; + } - // TODO: check redo write operation - } - fprintf(stdout, "\n"); - } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { - int write_block_count = 0; - for (off = 0; off < len; off += sl->flash_pgsz) { - // adjust last write size - size_t size = len - off > sl->flash_pgsz ? sl->flash_pgsz : len - off; + off = 0; - // unlock and set programming mode - unlock_flash_if(sl); + if (len > pagesize) { + if (stm32l1_write_half_pages(sl, addr, base, len, pagesize) == -1) { + // this may happen on a blank device! + WLOG("\nwrite_half_pages failed == -1\n"); + } else { + off = (size_t)(len / pagesize) * pagesize; + } + } - if (sl->flash_type != STLINK_FLASH_TYPE_F1_XL) { set_flash_cr_pg(sl, BANK_1); } + // write remaining word in program memory + for (; off < len; off += sizeof(uint32_t)) { + uint32_t data; - DLOG("Finished unlocking flash, running loader!\n"); + if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) { + fprintf(stdout, "\r%3u/%3u pages written", + (unsigned int)(off / sl->flash_pgsz), + (unsigned int)(len / sl->flash_pgsz)); + fflush(stdout); + } - if (stlink_flash_loader_run(sl, fl, addr + (uint32_t)off, base + off, size) == -1) { - ELOG("stlink_flash_loader_run(%#x) failed! == -1\n", (unsigned)(addr + off)); - return(-1); - } + write_uint32((unsigned char *)&data, *(uint32_t *)(base + off)); + stlink_write_debug32(sl, addr + (uint32_t)off, data); - lock_flash(sl); + // wait for sr.busy to be cleared + do { + stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); + } while ((val & (1 << 0)) != 0); - if (sl->verbose >= 1) { - // show progress; writing procedure is slow and previous errors are misleading - fprintf(stdout, "\r%3u/%3u pages written", ++write_block_count, - (unsigned int)((len + sl->flash_pgsz - 1) / sl->flash_pgsz)); - fflush(stdout); - } - } - if (sl->verbose >= 1) { - fprintf(stdout, "\n"); - } - } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { - for (off = 0; off < len;) { - // Program STM32H7x with 64-byte Flash words - size_t chunk = (len - off > 64) ? 64 : len - off; - memcpy(sl->q_buf, base + off, chunk); - stlink_write_mem32(sl, addr + (uint32_t)off, 64); - wait_flash_busy(sl); - - off += chunk; - - if (sl->verbose >= 1) { - // show progress - fprintf(stdout, "\r%u/%u bytes written", (unsigned int)off, (unsigned int)len); - fflush(stdout); - } - } - if (sl->verbose >= 1) { - fprintf(stdout, "\n"); - } + // TODO: check redo write operation + } + fprintf(stdout, "\n"); + } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + int write_block_count = 0; + for (off = 0; off < len; off += sl->flash_pgsz) { + // adjust last write size + size_t size = len - off > sl->flash_pgsz ? sl->flash_pgsz : len - off; + + // unlock and set programming mode + unlock_flash_if(sl); + + DLOG("Finished unlocking flash, running loader!\n"); + + if (stlink_flash_loader_run(sl, fl, addr + (uint32_t)off, base + off, + size) == -1) { + ELOG("stlink_flash_loader_run(%#x) failed! == -1\n", + (unsigned)(addr + off)); + check_flash_error(sl); + return (-1); + } + + lock_flash(sl); + + if (sl->verbose >= 1) { + // show progress; writing procedure is slow and previous errors are + // misleading + fprintf(stdout, "\r%3u/%3u pages written", ++write_block_count, + (unsigned int)((len + sl->flash_pgsz - 1) / sl->flash_pgsz)); + fflush(stdout); + } + } + if (sl->verbose >= 1) { + fprintf(stdout, "\n"); + } + } else if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + for (off = 0; off < len;) { + // Program STM32H7x with 64-byte Flash words + size_t chunk = (len - off > 64) ? 64 : len - off; + memcpy(sl->q_buf, base + off, chunk); + stlink_write_mem32(sl, addr + (uint32_t)off, 64); + wait_flash_busy(sl); + + off += chunk; + + if (sl->verbose >= 1) { + // show progress + fprintf(stdout, "\r%u/%u bytes written", (unsigned int)off, + (unsigned int)len); + fflush(stdout); + } + } + if (sl->verbose >= 1) { + fprintf(stdout, "\n"); + } + } else { + return (-1); + } + + return check_flash_error(sl); +} + +int stlink_flashloader_stop(stlink_t *sl, flash_loader_t *fl) { + uint32_t dhcsr; + + if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || + (sl->flash_type == STLINK_FLASH_TYPE_F7) || + (sl->flash_type == STLINK_FLASH_TYPE_L4) || + (sl->flash_type == STLINK_FLASH_TYPE_WB) || + (sl->flash_type == STLINK_FLASH_TYPE_G0) || + (sl->flash_type == STLINK_FLASH_TYPE_G4) || + (sl->flash_type == STLINK_FLASH_TYPE_H7)) { + + clear_flash_cr_pg(sl, BANK_1); + if (sl->flash_type == STLINK_FLASH_TYPE_H7 && + sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { + clear_flash_cr_pg(sl, BANK_2); + } + lock_flash(sl); + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + uint32_t val; + uint32_t flash_regs_base; + if (sl->chip_id == STLINK_CHIPID_STM32_L0 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || + sl->chip_id == STLINK_CHIPID_STM32_L011) { + flash_regs_base = STM32L0_FLASH_REGS_ADDR; } else { - return(-1); + flash_regs_base = STM32L_FLASH_REGS_ADDR; } + // reset lock bits + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + val |= (1 << 0) | (1 << 1) | (1 << 2); + stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + } + + // enable interrupt + if (!stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr)) { + stlink_write_debug32(sl, STLINK_REG_DHCSR, + STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN | + (dhcsr & (~STLINK_REG_DHCSR_C_MASKINTS))); + } + + // restore DMA state + set_dma_state(sl, fl, 1); + + return (0); +} + +int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, + uint32_t len, uint8_t eraseonly) { + size_t off; + int ret; + flash_loader_t fl; + ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, + len, addr, addr); + // check addr range is inside the flash + stlink_calculate_pagesize(sl, addr); + + if (addr < sl->flash_base) { + ELOG("addr too low %#x < %#x\n", addr, sl->flash_base); + return (-1); + } else if ((addr + len) < addr) { + ELOG("addr overruns\n"); + return (-1); + } else if ((addr + len) > (sl->flash_base + sl->flash_size)) { + ELOG("addr too high\n"); + return (-1); + } else if (addr & 1) { + ELOG("unaligned addr 0x%x\n", addr); + return (-1); + } else if (len & 1) { + WLOG("unaligned len 0x%x -- padding with zero\n", len); + len += 1; + } else if (addr & (sl->flash_pgsz - 1)) { + ELOG("addr not a multiple of current pagesize (%u bytes), not supported, " + "check page start address and compare with flash module organisation " + "in related ST reference manual of your device.\n", + (unsigned)(sl->flash_pgsz)); + return (-1); + } + + // make sure we've loaded the context with the chip details + stlink_core_id(sl); + + // Erase each page + int page_count = 0; + + for (off = 0; off < len; + off += stlink_calculate_pagesize(sl, addr + (uint32_t)off)) { + // addr must be an addr inside the page + if (stlink_erase_flash_page(sl, addr + (uint32_t)off) == -1) { + ELOG("Failed to erase_flash_page(%#x) == -1\n", (unsigned)(addr + off)); + return (-1); + } + + ILOG("Flash page at addr: 0x%08lx erased\n", (unsigned long)(addr + off)); + page_count++; + } + + ILOG("Finished erasing %d pages of %u (%#x) bytes\n", page_count, + (unsigned)(sl->flash_pgsz), (unsigned)(sl->flash_pgsz)); + + if (eraseonly) { + return (0); + } + + ret = stlink_flashloader_start(sl, &fl); + if (ret) + return ret; + ret = stlink_flashloader_write(sl, &fl, addr, base, len); + if (ret) + return ret; + ret = stlink_flashloader_stop(sl, &fl); + if (ret) + return ret; - return(0); + return (stlink_verify_write_flash(sl, addr, base, len)); } -int stlink_flashloader_stop(stlink_t *sl) { - if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || - (sl->flash_type == STLINK_FLASH_TYPE_F7) || - (sl->flash_type == STLINK_FLASH_TYPE_L4) || - (sl->flash_type == STLINK_FLASH_TYPE_WB) || - (sl->flash_type == STLINK_FLASH_TYPE_G0) || - (sl->flash_type == STLINK_FLASH_TYPE_G4) || - (sl->flash_type == STLINK_FLASH_TYPE_H7)) { - - clear_flash_cr_pg(sl, BANK_1); - if (sl->flash_type == STLINK_FLASH_TYPE_H7 && sl->chip_flags & CHIP_F_HAS_DUAL_BANK) { - clear_flash_cr_pg(sl, BANK_2); - } - lock_flash(sl); - } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - uint32_t val; - uint32_t flash_regs_base; - if (sl->chip_id == STLINK_CHIPID_STM32_L0 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || - sl->chip_id == STLINK_CHIPID_STM32_L011) { - flash_regs_base = STM32L0_FLASH_REGS_ADDR; - } else { - flash_regs_base = STM32L_FLASH_REGS_ADDR; - } - // reset lock bits - stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - val |= (1 << 0) | (1 << 1) | (1 << 2); - stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - } - - return(0); -} - -int stlink_write_flash( - stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len, uint8_t eraseonly) { - size_t off; - int ret; - flash_loader_t fl; - ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr); - // check addr range is inside the flash - stlink_calculate_pagesize(sl, addr); - - if (addr < sl->flash_base) { - ELOG("addr too low %#x < %#x\n", addr, sl->flash_base); - return(-1); - } else if ((addr + len) < addr) { - ELOG("addr overruns\n"); - return(-1); - } else if ((addr + len) > (sl->flash_base + sl->flash_size)) { - ELOG("addr too high\n"); - return(-1); - } else if (addr & 1) { - ELOG("unaligned addr 0x%x\n", addr); - return(-1); - } else if (len & 1) { - WLOG("unaligned len 0x%x -- padding with zero\n", len); - len += 1; - } else if (addr & (sl->flash_pgsz - 1)) { - ELOG("addr not a multiple of current pagesize (%u bytes), not supported, " - "check page start address and compare with flash module organisation " - "in related ST reference manual of your device.\n", (unsigned)(sl->flash_pgsz)); - return(-1); +// TODO: length not checked +static uint8_t stlink_parse_hex(const char *hex) { + uint8_t d[2]; + + for (int i = 0; i < 2; ++i) { + char c = *(hex + i); + + if (c >= '0' && c <= '9') { + d[i] = c - '0'; + } else if (c >= 'A' && c <= 'F') { + d[i] = c - 'A' + 10; + } else if (c >= 'a' && c <= 'f') { + d[i] = c - 'a' + 10; + } else { + return (0); // error } + } - // make sure we've loaded the context with the chip details - stlink_core_id(sl); - - // Erase each page - int page_count = 0; + return ((d[0] << 4) | (d[1])); +} - for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + (uint32_t)off)) { - // addr must be an addr inside the page - if (stlink_erase_flash_page(sl, addr + (uint32_t)off) == -1) { - ELOG("Failed to erase_flash_page(%#x) == -1\n", (unsigned)(addr + off)); - return(-1); - } +int stlink_parse_ihex(const char *path, uint8_t erased_pattern, uint8_t **mem, + size_t *size, uint32_t *begin) { + int res = 0; + *begin = UINT32_MAX; + uint8_t *data = NULL; + uint32_t end = 0; + bool eof_found = false; - ILOG("Flash page at addr: 0x%08lx erased\n", (unsigned long)(addr + off)); - page_count++; - } - - ILOG("Finished erasing %d pages of %u (%#x) bytes\n", - page_count, (unsigned)(sl->flash_pgsz), (unsigned)(sl->flash_pgsz)); + for (int scan = 0; (res == 0) && (scan < 2); ++scan) { + // parse file two times - first to find memory range, second - to fill it + if (scan == 1) { + if (!eof_found) { + ELOG("No EoF recond\n"); + res = -1; + break; + } - if (eraseonly) { return(0); } + if (*begin >= end) { + ELOG("No data found in file\n"); + res = -1; + break; + } - ret = stlink_flashloader_start(sl, &fl); - if (ret) - return ret; - ret = stlink_flashloader_write(sl, &fl, addr, base, len); - if (ret) - return ret; - ret = stlink_flashloader_stop(sl); - if (ret) - return ret; + *size = (end - *begin) + 1; + data = calloc(*size, 1); // use calloc to get NULL if out of memory - return(stlink_verify_write_flash(sl, addr, base, len)); -} + if (!data) { + ELOG("Cannot allocate %u bytes\n", (unsigned)(*size)); + res = -1; + break; + } -// TODO: length not checked -static uint8_t stlink_parse_hex(const char* hex) { - uint8_t d[2]; - - for (int i = 0; i < 2; ++i) { - char c = *(hex + i); - - if (c >= '0' && c <= '9') { - d[i] = c - '0'; - } else if (c >= 'A' && c <= 'F') { - d[i] = c - 'A' + 10; - } else if (c >= 'a' && c <= 'f') { - d[i] = c - 'a' + 10; - } else { - return(0); // error - } + memset(data, erased_pattern, *size); } - return((d[0] << 4) | (d[1])); -} - -int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, size_t * size, - uint32_t * begin) { - int res = 0; - *begin = UINT32_MAX; - uint8_t* data = NULL; - uint32_t end = 0; - bool eof_found = false; + FILE *file = fopen(path, "r"); - for (int scan = 0; (res == 0) && (scan < 2); ++scan) { - // parse file two times - first to find memory range, second - to fill it - if (scan == 1) { - if (!eof_found) { - ELOG("No EoF recond\n"); - res = -1; - break; - } - - if (*begin >= end) { - ELOG("No data found in file\n"); - res = -1; - break; - } + if (!file) { + ELOG("Cannot open file\n"); + res = -1; + break; + } - *size = (end - *begin) + 1; - data = calloc(*size, 1); // use calloc to get NULL if out of memory + uint32_t lba = 0; + char line[1 + 5 * 2 + 255 * 2 + 2]; - if (!data) { - ELOG("Cannot allocate %u bytes\n", (unsigned)(*size)); - res = -1; - break; - } + while (fgets(line, sizeof(line), file)) { + if (line[0] == '\n' || line[0] == '\r') { + continue; + } // skip empty lines - memset(data, erased_pattern, *size); - } + if (line[0] != ':') { // no marker - wrong file format + ELOG("Wrong file format - no marker\n"); + res = -1; + break; + } - FILE* file = fopen(path, "r"); + size_t l = strlen(line); - if (!file) { - ELOG("Cannot open file\n"); - res = -1; - break; - } + while (l > 0 && (line[l - 1] == '\n' || line[l - 1] == '\r')) { + --l; + } // trim EoL - uint32_t lba = 0; - char line[1 + 5 * 2 + 255 * 2 + 2]; + if ((l < 11) || + (l == + (sizeof(line) - 1))) { // line too short or long - wrong file format + ELOG("Wrong file format - wrong line length\n"); + res = -1; + break; + } - while (fgets(line, sizeof(line), file)) { - if (line[0] == '\n' || line[0] == '\r') { continue; } // skip empty lines + uint8_t chksum = 0; // check sum - if (line[0] != ':') { // no marker - wrong file format - ELOG("Wrong file format - no marker\n"); - res = -1; - break; - } + for (size_t i = 1; i < l; i += 2) { + chksum += stlink_parse_hex(line + i); + } - size_t l = strlen(line); + if (chksum != 0) { + ELOG("Wrong file format - checksum mismatch\n"); + res = -1; + break; + } - while (l > 0 && (line[l - 1] == '\n' || line[l - 1] == '\r')) { --l; } // trim EoL + uint8_t reclen = stlink_parse_hex(line + 1); - if ((l < 11) || (l == (sizeof(line) - 1))) { // line too short or long - wrong file format - ELOG("Wrong file format - wrong line length\n"); - res = -1; - break; - } - - uint8_t chksum = 0; // check sum + if (((uint32_t)reclen + 5) * 2 + 1 != l) { + ELOG("Wrong file format - record length mismatch\n"); + res = -1; + break; + } - for (size_t i = 1; i < l; i += 2) { chksum += stlink_parse_hex(line + i); } + uint16_t offset = ((uint16_t)stlink_parse_hex(line + 3) << 8) | + ((uint16_t)stlink_parse_hex(line + 5)); + uint8_t rectype = stlink_parse_hex(line + 7); - if (chksum != 0) { - ELOG("Wrong file format - checksum mismatch\n"); - res = -1; - break; - } + switch (rectype) { + case 0: /* Data */ + if (scan == 0) { + uint32_t b = lba + offset; + uint32_t e = b + reclen - 1; - uint8_t reclen = stlink_parse_hex(line + 1); + if (b < *begin) { + *begin = b; + } - if (((uint32_t)reclen + 5) * 2 + 1 != l) { - ELOG("Wrong file format - record length mismatch\n"); - res = -1; - break; - } + if (e > end) { + end = e; + } + } else { + for (uint8_t i = 0; i < reclen; ++i) { + uint8_t b = stlink_parse_hex(line + 9 + i * 2); + uint32_t addr = lba + offset + i; - uint16_t offset = ((uint16_t)stlink_parse_hex(line + 3) << 8) | - ((uint16_t)stlink_parse_hex(line + 5)); - uint8_t rectype = stlink_parse_hex(line + 7); - - switch (rectype) { - case 0: /* Data */ - if (scan == 0) { - uint32_t b = lba + offset; - uint32_t e = b + reclen - 1; - - if (b < *begin) { *begin = b; } - - if (e > end) { end = e; } - } else { - for (uint8_t i = 0; i < reclen; ++i) { - uint8_t b = stlink_parse_hex(line + 9 + i * 2); - uint32_t addr = lba + offset + i; - - if (addr >= *begin && addr <= end) { data[addr - *begin] = b; } - } - } - break; - case 1: /* EoF */ - eof_found = true; - break; - case 2: /* Extended Segment Address, unexpected */ - res = -1; - break; - case 3: /* Start Segment Address, unexpected */ - res = -1; - break; - case 4: /* Extended Linear Address */ - if (reclen == 2) { - lba = ((uint32_t)stlink_parse_hex(line + 9) << 24) | - ((uint32_t)stlink_parse_hex(line + 11) << 16); - } else { - ELOG("Wrong file format - wrong LBA length\n"); - res = -1; - } - break; - case 5: /* Start Linear Address - expected, but ignore */ - break; - default: - ELOG("Wrong file format - unexpected record type %d\n", rectype); - res = -1; + if (addr >= *begin && addr <= end) { + data[addr - *begin] = b; } - - if (res != 0) { break; } + } + } + break; + case 1: /* EoF */ + eof_found = true; + break; + case 2: /* Extended Segment Address, unexpected */ + res = -1; + break; + case 3: /* Start Segment Address, unexpected */ + res = -1; + break; + case 4: /* Extended Linear Address */ + if (reclen == 2) { + lba = ((uint32_t)stlink_parse_hex(line + 9) << 24) | + ((uint32_t)stlink_parse_hex(line + 11) << 16); + } else { + ELOG("Wrong file format - wrong LBA length\n"); + res = -1; } + break; + case 5: /* Start Linear Address - expected, but ignore */ + break; + default: + ELOG("Wrong file format - unexpected record type %d\n", rectype); + res = -1; + } - fclose(file); + if (res != 0) { + break; + } } - if (res == 0) { - *mem = data; - } else { - free(data); - } + fclose(file); + } - return(res); -} + if (res == 0) { + *mem = data; + } else { + free(data); + } -uint8_t stlink_get_erased_pattern(stlink_t *sl) { - if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - return(0x00); - } else { - return(0xff); - } + return (res); } -int stlink_mwrite_flash(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr_t addr) { - /* Write the block in flash at addr */ - int err; - unsigned int num_empty, idx; - uint8_t erased_pattern = stlink_get_erased_pattern(sl); - - /* - * This optimisation may cause unexpected garbage data remaining. - * Therfore it is turned off by default. - */ - if (sl->opt) { - idx = (unsigned int)length; - - for (num_empty = 0; num_empty != length; ++num_empty) - if (data[--idx] != erased_pattern) { break; } +uint8_t stlink_get_erased_pattern(stlink_t *sl) { + if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + return (0x00); + } else { + return (0xff); + } +} + +int stlink_mwrite_flash(stlink_t *sl, uint8_t *data, uint32_t length, + stm32_addr_t addr) { + /* Write the block in flash at addr */ + int err; + unsigned int num_empty, idx; + uint8_t erased_pattern = stlink_get_erased_pattern(sl); + + /* + * This optimisation may cause unexpected garbage data remaining. + * Therfore it is turned off by default. + */ + if (sl->opt) { + idx = (unsigned int)length; + + for (num_empty = 0; num_empty != length; ++num_empty) + if (data[--idx] != erased_pattern) { + break; + } - num_empty -= (num_empty & 3); // Round down to words + num_empty -= (num_empty & 3); // Round down to words - if (num_empty != 0) { - ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, erased_pattern); - } - } else { - num_empty = 0; + if (num_empty != 0) { + ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, + erased_pattern); } + } else { + num_empty = 0; + } - /* - * TODO: investigate a kind of weird behaviour here: - * If the file is identified to be all-empty and four-bytes aligned, - * still flash the whole file even if ignoring message is printed. - */ - err = stlink_write_flash(sl, addr, data, - (num_empty == length) ? (uint32_t)length : (uint32_t)length - num_empty, - num_empty == length); - stlink_fwrite_finalize(sl, addr); - return(err); + /* + * TODO: investigate a kind of weird behaviour here: + * If the file is identified to be all-empty and four-bytes aligned, + * still flash the whole file even if ignoring message is printed. + */ + err = stlink_write_flash(sl, addr, data, + (num_empty == length) ? (uint32_t)length + : (uint32_t)length - num_empty, + num_empty == length); + stlink_fwrite_finalize(sl, addr); + return (err); } /** @@ -3315,49 +3791,53 @@ int stlink_mwrite_flash(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr * @param addr where to start writing * @return 0 on success, -ve on failure. */ -int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { - /* Write the file in flash at addr */ - int err; - unsigned int num_empty, idx; - uint8_t erased_pattern = stlink_get_erased_pattern(sl); - mapped_file_t mf = MAPPED_FILE_INITIALIZER; - - if (map_file(&mf, path) == -1) { - ELOG("map_file() == -1\n"); - return(-1); +int stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { + /* Write the file in flash at addr */ + int err; + unsigned int num_empty, idx; + uint8_t erased_pattern = stlink_get_erased_pattern(sl); + mapped_file_t mf = MAPPED_FILE_INITIALIZER; + + if (map_file(&mf, path) == -1) { + ELOG("map_file() == -1\n"); + return (-1); + } + + printf("file %s ", path); + md5_calculate(&mf); + stlink_checksum(&mf); + + if (sl->opt) { + idx = (unsigned int)mf.len; + + for (num_empty = 0; num_empty != mf.len; ++num_empty) { + if (mf.base[--idx] != erased_pattern) { + break; + } } - printf("file %s ", path); - md5_calculate(&mf); - stlink_checksum(&mf); - - if (sl->opt) { - idx = (unsigned int)mf.len; + num_empty -= (num_empty & 3); // round down to words - for (num_empty = 0; num_empty != mf.len; ++num_empty) { - if (mf.base[--idx] != erased_pattern) { break; } - } - - num_empty -= (num_empty & 3); // round down to words - - if (num_empty != 0) { - ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, erased_pattern); - } - } else { - num_empty = 0; + if (num_empty != 0) { + ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, + erased_pattern); } + } else { + num_empty = 0; + } - /* - * TODO: investigate a kind of weird behaviour here: - * If the file is identified to be all-empty and four-bytes aligned, - * still flash the whole file even if ignoring message is printed. - */ - err = stlink_write_flash(sl, addr, mf.base, - (num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty, - num_empty == mf.len); - stlink_fwrite_finalize(sl, addr); - unmap_file(&mf); - return(err); + /* + * TODO: investigate a kind of weird behaviour here: + * If the file is identified to be all-empty and four-bytes aligned, + * still flash the whole file even if ignoring message is printed. + */ + err = stlink_write_flash(sl, addr, mf.base, + (num_empty == mf.len) ? (uint32_t)mf.len + : (uint32_t)mf.len - num_empty, + num_empty == mf.len); + stlink_fwrite_finalize(sl, addr); + unmap_file(&mf); + return (err); } /** @@ -3367,33 +3847,35 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { * @param base option bytes to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_gx( - stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { - /* Write options bytes */ - uint32_t val; - int ret = 0; - (void)len; - uint32_t data; +static int stlink_write_option_bytes_gx(stlink_t *sl, uint8_t *base, + stm32_addr_t addr, uint32_t len) { + /* Write options bytes */ + uint32_t val; + int ret = 0; + (void)len; + uint32_t data; - write_uint32((unsigned char*)&data, *(uint32_t*)(base)); - WLOG("Writing option bytes %#10x to %#10x\n", data, addr); - stlink_write_debug32(sl, STM32Gx_FLASH_OPTR, data); + clear_flash_error(sl); - // Set Options Start bit - stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); - val |= (1 << STM32Gx_FLASH_CR_OPTSTRT); - stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); + write_uint32((unsigned char *)&data, *(uint32_t *)(base)); + WLOG("Writing option bytes %#10x to %#10x\n", data, addr); + stlink_write_debug32(sl, STM32Gx_FLASH_OPTR, data); - wait_flash_busy(sl); + // Set Options Start bit + stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); + val |= (1 << STM32Gx_FLASH_CR_OPTSTRT); + stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); + + wait_flash_busy(sl); - ret = check_flash_error(sl); + ret = check_flash_error(sl); - // Reload options - stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); - val |= (1 << STM32Gx_FLASH_CR_OBL_LAUNCH); - stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); + // Reload options + stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); + val |= (1 << STM32Gx_FLASH_CR_OBL_LAUNCH); + stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); - return(ret); + return (ret); } /** @@ -3403,36 +3885,39 @@ static int stlink_write_option_bytes_gx( * @param base option bytes to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_l0( - stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { - uint32_t flash_base = get_stm32l0_flash_base(sl); - uint32_t val; - uint32_t data; - int ret = 0; - - // Clear errors - stlink_write_debug32(sl, flash_base + FLASH_SR_OFF, STM32L0_FLASH_REGS_ADDR); +static int stlink_write_option_bytes_l0(stlink_t *sl, uint8_t *base, + stm32_addr_t addr, uint32_t len) { + uint32_t flash_base = get_stm32l0_flash_base(sl); + uint32_t val; + uint32_t data; + int ret = 0; - while (len != 0) { - write_uint32((unsigned char*)&data, *(uint32_t*)(base)); // write options bytes + // Clear errors + clear_flash_error(sl); - WLOG("Writing option bytes %#10x to %#10x\n", data, addr); - stlink_write_debug32(sl, addr, data); - wait_flash_busy(sl); + while (len != 0) { + write_uint32((unsigned char *)&data, + *(uint32_t *)(base)); // write options bytes - if ((ret = check_flash_error(sl))) { break; } + WLOG("Writing option bytes %#10x to %#10x\n", data, addr); + stlink_write_debug32(sl, addr, data); + wait_flash_busy(sl); - len -= 4; - addr += 4; - base += 4; + if ((ret = check_flash_error(sl))) { + break; } - // Reload options - stlink_read_debug32(sl, flash_base + FLASH_PECR_OFF, &val); - val |= (1 << STM32L0_FLASH_OBL_LAUNCH); - stlink_write_debug32(sl, flash_base + FLASH_PECR_OFF, val); + len -= 4; + addr += 4; + base += 4; + } + + // Reload options + stlink_read_debug32(sl, flash_base + FLASH_PECR_OFF, &val); + val |= (1 << STM32L0_FLASH_OBL_LAUNCH); + stlink_write_debug32(sl, flash_base + FLASH_PECR_OFF, val); - return(ret); + return (ret); } /** @@ -3442,36 +3927,38 @@ static int stlink_write_option_bytes_l0( * @param base option bytes to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_l4( - stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { +static int stlink_write_option_bytes_l4(stlink_t *sl, uint8_t *base, + stm32_addr_t addr, uint32_t len) { - uint32_t val; - int ret = 0; - (void)addr; - (void)len; + uint32_t val; + int ret = 0; + (void)addr; + (void)len; - // write options bytes - uint32_t data; - write_uint32((unsigned char*)&data, *(uint32_t*)(base)); - WLOG("Writing option bytes 0x%04x\n", data); - stlink_write_debug32(sl, STM32L4_FLASH_OPTR, data); + // Clear errors + clear_flash_error(sl); - // set options start bit - stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); - val |= (1 << STM32L4_FLASH_CR_OPTSTRT); - stlink_write_debug32(sl, STM32L4_FLASH_CR, val); + // write options bytes + uint32_t data; + write_uint32((unsigned char *)&data, *(uint32_t *)(base)); + WLOG("Writing option bytes 0x%04x\n", data); + stlink_write_debug32(sl, STM32L4_FLASH_OPTR, data); - wait_flash_busy(sl); - ret = check_flash_error(sl); + // set options start bit + stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); + val |= (1 << STM32L4_FLASH_CR_OPTSTRT); + stlink_write_debug32(sl, STM32L4_FLASH_CR, val); - // apply options bytes immediate - stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); - val |= (1 << STM32L4_FLASH_CR_OBL_LAUNCH); - stlink_write_debug32(sl, STM32L4_FLASH_CR, val); + wait_flash_busy(sl); + ret = check_flash_error(sl); - return(ret); -} + // apply options bytes immediate + stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); + val |= (1 << STM32L4_FLASH_CR_OBL_LAUNCH); + stlink_write_debug32(sl, STM32L4_FLASH_CR, val); + return (ret); +} /** * Write option bytes @@ -3479,24 +3966,28 @@ static int stlink_write_option_bytes_l4( * @param option_byte value to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_f4( - stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { - uint32_t option_byte; - int ret = 0; - (void)addr; - (void)len; +static int stlink_write_option_bytes_f4(stlink_t *sl, uint8_t *base, + stm32_addr_t addr, uint32_t len) { + uint32_t option_byte; + int ret = 0; + (void)addr; + (void)len; - write_uint32((unsigned char*)&option_byte, *(uint32_t*)(base)); + // Clear errors + clear_flash_error(sl); - // write option byte, ensuring we dont lock opt, and set strt bit - stlink_write_debug32(sl, FLASH_F4_OPTCR, - (option_byte & ~(1 << FLASH_F4_OPTCR_LOCK)) | (1 << FLASH_F4_OPTCR_START)); + write_uint32((unsigned char *)&option_byte, *(uint32_t *)(base)); - wait_flash_busy(sl); - ret = check_flash_error(sl); + // write option byte, ensuring we dont lock opt, and set strt bit + stlink_write_debug32(sl, FLASH_F4_OPTCR, + (option_byte & ~(1 << FLASH_F4_OPTCR_LOCK)) | + (1 << FLASH_F4_OPTCR_START)); + + wait_flash_busy(sl); + ret = check_flash_error(sl); - // option bytes are reloaded at reset only, no obl. */ - return(ret); + // option bytes are reloaded at reset only, no obl. */ + return (ret); } /** @@ -3505,47 +3996,54 @@ static int stlink_write_option_bytes_f4( * @param option_byte value to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_f7(stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { - uint32_t option_byte; - int ret = 0; +static int stlink_write_option_bytes_f7(stlink_t *sl, uint8_t *base, + stm32_addr_t addr, uint32_t len) { + uint32_t option_byte; + int ret = 0; - //(void) addr; - //(void) len; + // Clear errors + clear_flash_error(sl); - ILOG("Asked to write option byte %#10x to %#010x.\n", *(uint32_t*) (base), addr); - write_uint32((unsigned char*) &option_byte, *(uint32_t*) (base)); - ILOG("Write %d option bytes %#010x to %#010x!\n", len, option_byte, addr); + ILOG("Asked to write option byte %#10x to %#010x.\n", *(uint32_t *)(base), + addr); + write_uint32((unsigned char *)&option_byte, *(uint32_t *)(base)); + ILOG("Write %d option bytes %#010x to %#010x!\n", len, option_byte, addr); - if ( addr == 0 ) { - addr = FLASH_F7_OPTCR; - ILOG("No address provided, using %#10x\n", addr); - } + if (addr == 0) { + addr = FLASH_F7_OPTCR; + ILOG("No address provided, using %#10x\n", addr); + } - if ( addr == FLASH_F7_OPTCR ) { - /* write option byte, ensuring we dont lock opt, and set strt bit */ - stlink_write_debug32(sl, FLASH_F7_OPTCR, (option_byte & ~(1 << FLASH_F7_OPTCR_LOCK)) | (1 << FLASH_F7_OPTCR_START)); - } else if ( addr == FLASH_F7_OPTCR1 ) { - // Read FLASH_F7_OPTCR - uint32_t oldvalue; - stlink_read_debug32(sl, FLASH_F7_OPTCR, &oldvalue); - /* write option byte */ - stlink_write_debug32(sl, FLASH_F7_OPTCR1, option_byte); - // Write FLASH_F7_OPTCR lock and start address - stlink_write_debug32(sl, FLASH_F7_OPTCR, (oldvalue & ~(1 << FLASH_F7_OPTCR_LOCK)) | (1 << FLASH_F7_OPTCR_START)); - } else { - WLOG("WIP: write %#010x to address %#010x\n", option_byte, addr); - stlink_write_debug32(sl, addr, option_byte); - } + if (addr == FLASH_F7_OPTCR) { + /* write option byte, ensuring we dont lock opt, and set strt bit */ + stlink_write_debug32(sl, FLASH_F7_OPTCR, + (option_byte & ~(1 << FLASH_F7_OPTCR_LOCK)) | + (1 << FLASH_F7_OPTCR_START)); + } else if (addr == FLASH_F7_OPTCR1) { + // Read FLASH_F7_OPTCR + uint32_t oldvalue; + stlink_read_debug32(sl, FLASH_F7_OPTCR, &oldvalue); + /* write option byte */ + stlink_write_debug32(sl, FLASH_F7_OPTCR1, option_byte); + // Write FLASH_F7_OPTCR lock and start address + stlink_write_debug32(sl, FLASH_F7_OPTCR, + (oldvalue & ~(1 << FLASH_F7_OPTCR_LOCK)) | + (1 << FLASH_F7_OPTCR_START)); + } else { + WLOG("WIP: write %#010x to address %#010x\n", option_byte, addr); + stlink_write_debug32(sl, addr, option_byte); + } - wait_flash_busy(sl); + wait_flash_busy(sl); - ret = check_flash_error(sl); - if (!ret) - ILOG("Wrote %d option bytes %#010x to %#010x!\n", len, *(uint32_t*) base, addr); + ret = check_flash_error(sl); + if (!ret) + ILOG("Wrote %d option bytes %#010x to %#010x!\n", len, *(uint32_t *)base, + addr); - /* option bytes are reloaded at reset only, no obl. */ + /* option bytes are reloaded at reset only, no obl. */ - return ret; + return ret; } /** @@ -3556,64 +4054,67 @@ static int stlink_write_option_bytes_f7(stlink_t *sl, uint8_t* base, stm32_addr_ * @param len number of bytes to write (must be multiple of 4) * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_h7( - stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { - uint32_t val; - uint32_t data; - - // Wait until previous flash option has completed - wait_flash_busy(sl); - - // Clear previous error - stlink_write_debug32(sl, FLASH_H7_OPTCCR, 1 << FLASH_H7_OPTCCR_CLR_OPTCHANGEERR); - - while (len != 0) { - switch (addr) { - case FLASH_H7_REGS_ADDR + 0x20: // FLASH_OPTSR_PRG - case FLASH_H7_REGS_ADDR + 0x2c: // FLASH_PRAR_PRG1 - case FLASH_H7_REGS_ADDR + 0x34: // FLASH_SCAR_PRG1 - case FLASH_H7_REGS_ADDR + 0x3c: // FLASH_WPSN_PRG1 - case FLASH_H7_REGS_ADDR + 0x44: // FLASH_BOOT_PRG - /* Write to FLASH_xxx_PRG registers */ - write_uint32((unsigned char*)&data, *(uint32_t*)(base)); // write options bytes - - WLOG("Writing option bytes %#10x to %#10x\n", data, addr); - - /* Skip if the value in the CUR register is identical */ - stlink_read_debug32(sl, addr - 4, &val); - if (val == data) { - break; - } - - /* Write new option byte values and start modification */ - stlink_write_debug32(sl, addr, data); - stlink_read_debug32(sl, FLASH_H7_OPTCR, &val); - val |= (1 << FLASH_H7_OPTCR_OPTSTART); - stlink_write_debug32(sl, FLASH_H7_OPTCR, val); - - /* Wait for the option bytes modification to complete */ - do { - stlink_read_debug32(sl, FLASH_H7_OPTSR_CUR, &val); - } while ((val & (1 << FLASH_H7_OPTSR_OPT_BUSY)) != 0); - - /* Check for errors */ - if ((val & (1 << FLASH_H7_OPTSR_OPTCHANGEERR)) != 0) { - stlink_write_debug32(sl, FLASH_H7_OPTCCR, 1 << FLASH_H7_OPTCCR_CLR_OPTCHANGEERR); - return -1; - } - break; - - default: - /* Skip non-programmable registers */ - break; - } +static int stlink_write_option_bytes_h7(stlink_t *sl, uint8_t *base, + stm32_addr_t addr, uint32_t len) { + uint32_t val; + uint32_t data; + + // Wait until previous flash option has completed + wait_flash_busy(sl); + + // Clear previous error + stlink_write_debug32(sl, FLASH_H7_OPTCCR, + 1 << FLASH_H7_OPTCCR_CLR_OPTCHANGEERR); + + while (len != 0) { + switch (addr) { + case FLASH_H7_REGS_ADDR + 0x20: // FLASH_OPTSR_PRG + case FLASH_H7_REGS_ADDR + 0x2c: // FLASH_PRAR_PRG1 + case FLASH_H7_REGS_ADDR + 0x34: // FLASH_SCAR_PRG1 + case FLASH_H7_REGS_ADDR + 0x3c: // FLASH_WPSN_PRG1 + case FLASH_H7_REGS_ADDR + 0x44: // FLASH_BOOT_PRG + /* Write to FLASH_xxx_PRG registers */ + write_uint32((unsigned char *)&data, + *(uint32_t *)(base)); // write options bytes + + WLOG("Writing option bytes %#10x to %#10x\n", data, addr); + + /* Skip if the value in the CUR register is identical */ + stlink_read_debug32(sl, addr - 4, &val); + if (val == data) { + break; + } + + /* Write new option byte values and start modification */ + stlink_write_debug32(sl, addr, data); + stlink_read_debug32(sl, FLASH_H7_OPTCR, &val); + val |= (1 << FLASH_H7_OPTCR_OPTSTART); + stlink_write_debug32(sl, FLASH_H7_OPTCR, val); + + /* Wait for the option bytes modification to complete */ + do { + stlink_read_debug32(sl, FLASH_H7_OPTSR_CUR, &val); + } while ((val & (1 << FLASH_H7_OPTSR_OPT_BUSY)) != 0); + + /* Check for errors */ + if ((val & (1 << FLASH_H7_OPTSR_OPTCHANGEERR)) != 0) { + stlink_write_debug32(sl, FLASH_H7_OPTCCR, + 1 << FLASH_H7_OPTCCR_CLR_OPTCHANGEERR); + return -1; + } + break; - len -= 4; - addr += 4; - base += 4; + default: + /* Skip non-programmable registers */ + break; } - return 0; + len -= 4; + addr += 4; + base += 4; + } + + return 0; } /** @@ -3622,8 +4123,9 @@ static int stlink_write_option_bytes_h7( * @param option_byte value to write * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register_Gx(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, option_byte); +int stlink_read_option_control_register_Gx(stlink_t *sl, + uint32_t *option_byte) { + return stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, option_byte); } /** @@ -3632,8 +4134,8 @@ int stlink_read_option_control_register_Gx(stlink_t *sl, uint32_t* option_byte) * @param option_byte value to write * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes_Gx(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_option_control_register_Gx(sl, option_byte); +int stlink_read_option_bytes_Gx(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_option_control_register_Gx(sl, option_byte); } /** @@ -3642,8 +4144,9 @@ int stlink_read_option_bytes_Gx(stlink_t *sl, uint32_t* option_byte) { * @param option_byte value to write * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register_f2(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_debug32(sl, FLASH_F2_OPT_CR, option_byte); +int stlink_read_option_control_register_f2(stlink_t *sl, + uint32_t *option_byte) { + return stlink_read_debug32(sl, FLASH_F2_OPT_CR, option_byte); } /** @@ -3652,8 +4155,8 @@ int stlink_read_option_control_register_f2(stlink_t *sl, uint32_t* option_byte) * @param option_byte value to write * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_option_control_register_f2(sl, option_byte); +int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_option_control_register_f2(sl, option_byte); } /** @@ -3662,8 +4165,9 @@ int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte) { * @param option_byte value to read * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register_f4(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_debug32(sl, FLASH_F4_OPTCR, option_byte); +int stlink_read_option_control_register_f4(stlink_t *sl, + uint32_t *option_byte) { + return stlink_read_debug32(sl, FLASH_F4_OPTCR, option_byte); } /** @@ -3672,8 +4176,8 @@ int stlink_read_option_control_register_f4(stlink_t *sl, uint32_t* option_byte) * @param option_byte value to read * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_option_control_register_f4(sl, option_byte); +int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_option_control_register_f4(sl, option_byte); } /** @@ -3682,9 +4186,10 @@ int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t* option_byte) { * @param option_byte value to read * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register_f7(stlink_t *sl, uint32_t* option_byte) { - DLOG("@@@@ Read option control register byte from %#10x\n", FLASH_F7_OPTCR); - return stlink_read_debug32(sl, FLASH_F7_OPTCR, option_byte); +int stlink_read_option_control_register_f7(stlink_t *sl, + uint32_t *option_byte) { + DLOG("@@@@ Read option control register byte from %#10x\n", FLASH_F7_OPTCR); + return stlink_read_debug32(sl, FLASH_F7_OPTCR, option_byte); } /** @@ -3693,9 +4198,11 @@ int stlink_read_option_control_register_f7(stlink_t *sl, uint32_t* option_byte) * @param option_byte value to read * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register1_f7(stlink_t *sl, uint32_t* option_byte) { - DLOG("@@@@ Read option control register 1 byte from %#10x\n", FLASH_F7_OPTCR1); - return stlink_read_debug32(sl, FLASH_F7_OPTCR1, option_byte); +int stlink_read_option_control_register1_f7(stlink_t *sl, + uint32_t *option_byte) { + DLOG("@@@@ Read option control register 1 byte from %#10x\n", + FLASH_F7_OPTCR1); + return stlink_read_debug32(sl, FLASH_F7_OPTCR1, option_byte); } /** @@ -3704,9 +4211,9 @@ int stlink_read_option_control_register1_f7(stlink_t *sl, uint32_t* option_byte) * @param option_byte value to read * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes_boot_add_f7(stlink_t *sl, uint32_t* option_byte) { - DLOG("@@@@ Read option byte boot address\n"); - return stlink_read_option_control_register1_f7(sl, option_byte); +int stlink_read_option_bytes_boot_add_f7(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option byte boot address\n"); + return stlink_read_option_control_register1_f7(sl, option_byte); } /** @@ -3718,18 +4225,22 @@ int stlink_read_option_bytes_boot_add_f7(stlink_t *sl, uint32_t* option_byte) { * Since multiple bytes can be read, we read and print all but one here * and then return the last one just like other devices */ -int stlink_read_option_bytes_f7(stlink_t *sl, uint32_t* option_byte) { - int err = -1; - for (uint8_t counter = 0; counter < (sl->option_size / 4 - 1); counter++) { - err = stlink_read_debug32(sl, sl->option_base + counter * sizeof(uint32_t), option_byte); - if (err == -1) { - return err; - } else { - printf("%08x\n", *option_byte); - } +int stlink_read_option_bytes_f7(stlink_t *sl, uint32_t *option_byte) { + int err = -1; + for (uint32_t counter = 0; counter < (sl->option_size / 4 - 1); counter++) { + err = stlink_read_debug32(sl, sl->option_base + counter * sizeof(uint32_t), + option_byte); + if (err == -1) { + return err; + } else { + printf("%08x\n", *option_byte); } + } - return stlink_read_debug32(sl, sl->option_base + (uint32_t) (sl->option_size / 4 - 1) * sizeof(uint32_t), option_byte); + return stlink_read_debug32( + sl, + sl->option_base + (uint32_t)(sl->option_size / 4 - 1) * sizeof(uint32_t), + option_byte); } /** @@ -3738,9 +4249,9 @@ int stlink_read_option_bytes_f7(stlink_t *sl, uint32_t* option_byte) { * @param option_byte option value * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t* option_byte) { - DLOG("@@@@ Read option bytes boot address from %#10x\n", sl->option_base); - return stlink_read_debug32(sl, sl->option_base, option_byte); +int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option bytes boot address from %#10x\n", sl->option_base); + return stlink_read_debug32(sl, sl->option_base, option_byte); } /** @@ -3749,7 +4260,8 @@ int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t* option_byte) { * @param option_byte value to read * @return 0 on success, -ve on failure. */ -//int stlink_read_option_bytes_boot_add_generic(stlink_t *sl, uint32_t* option_byte) { +// int stlink_read_option_bytes_boot_add_generic(stlink_t *sl, uint32_t* +// option_byte) { // DLOG("@@@@ Read option bytes boot address from %#10x\n", sl->option_base); // return stlink_read_debug32(sl, sl->option_base, option_byte); //} @@ -3760,9 +4272,11 @@ int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t* option_byte) { * @param option_byte value to read * @return 0 on success, -ve on failure. */ -//int stlink_read_option_control_register_generic(stlink_t *sl, uint32_t* option_byte) { -// DLOG("@@@@ Read option control register byte from %#10x\n", sl->option_base); -// return stlink_read_debug32(sl, sl->option_base, option_byte); +// int stlink_read_option_control_register_generic(stlink_t *sl, uint32_t* +// option_byte) { +// DLOG("@@@@ Read option control register byte from %#10x\n", +// sl->option_base); return stlink_read_debug32(sl, sl->option_base, +// option_byte); //} /** @@ -3771,9 +4285,11 @@ int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t* option_byte) { * @param option_byte value to read * @return 0 on success, -ve on failure. */ -//int stlink_read_option_control_register1_generic(stlink_t *sl, uint32_t* option_byte) { -// DLOG("@@@@ Read option control register 1 byte from %#10x\n", sl->option_base); -// return stlink_read_debug32(sl, sl->option_base, option_byte); +// int stlink_read_option_control_register1_generic(stlink_t *sl, uint32_t* +// option_byte) { +// DLOG("@@@@ Read option control register 1 byte from %#10x\n", +// sl->option_base); return stlink_read_debug32(sl, sl->option_base, +// option_byte); //} /** @@ -3782,28 +4298,28 @@ int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t* option_byte) { * @param option_byte option value * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes32(stlink_t *sl, uint32_t* option_byte) { - if (sl->option_base == 0) { - ELOG("Option bytes read is currently not supported for connected chip\n"); - return(-1); - } - - switch (sl->chip_id) { - case STLINK_CHIPID_STM32_F2: - return stlink_read_option_bytes_f2(sl, option_byte); - case STLINK_CHIPID_STM32_F4: - case STLINK_CHIPID_STM32_F446: - return stlink_read_option_bytes_f4(sl, option_byte); - case STLINK_CHIPID_STM32_F7XXXX: - return stlink_read_option_bytes_f7(sl, option_byte); - case STLINK_CHIPID_STM32_G0_CAT1: - case STLINK_CHIPID_STM32_G0_CAT2: - case STLINK_CHIPID_STM32_G4_CAT2: - case STLINK_CHIPID_STM32_G4_CAT3: - return stlink_read_option_bytes_Gx(sl, option_byte); - default: - return stlink_read_option_bytes_generic(sl, option_byte); - } +int stlink_read_option_bytes32(stlink_t *sl, uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes read is currently not supported for connected chip\n"); + return (-1); + } + + switch (sl->chip_id) { + case STLINK_CHIPID_STM32_F2: + return stlink_read_option_bytes_f2(sl, option_byte); + case STLINK_CHIPID_STM32_F4: + case STLINK_CHIPID_STM32_F446: + return stlink_read_option_bytes_f4(sl, option_byte); + case STLINK_CHIPID_STM32_F7XXXX: + return stlink_read_option_bytes_f7(sl, option_byte); + case STLINK_CHIPID_STM32_G0_CAT1: + case STLINK_CHIPID_STM32_G0_CAT2: + case STLINK_CHIPID_STM32_G4_CAT2: + case STLINK_CHIPID_STM32_G4_CAT3: + return stlink_read_option_bytes_Gx(sl, option_byte); + default: + return stlink_read_option_bytes_generic(sl, option_byte); + } } /** @@ -3812,20 +4328,20 @@ int stlink_read_option_bytes32(stlink_t *sl, uint32_t* option_byte) { * @param option_byte option value * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes_boot_add32(stlink_t *sl, uint32_t* option_byte) -{ - if (sl->option_base == 0) { - ELOG("Option bytes boot address read is currently not supported for connected chip\n"); - return -1; - } - - switch (sl->chip_id) { - case STLINK_CHIPID_STM32_F7XXXX: - return stlink_read_option_bytes_boot_add_f7(sl, option_byte); - default: - return -1; - //return stlink_read_option_bytes_boot_add_generic(sl, option_byte); - } +int stlink_read_option_bytes_boot_add32(stlink_t *sl, uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes boot address read is currently not supported for " + "connected chip\n"); + return -1; + } + + switch (sl->chip_id) { + case STLINK_CHIPID_STM32_F7XXXX: + return stlink_read_option_bytes_boot_add_f7(sl, option_byte); + default: + return -1; + // return stlink_read_option_bytes_boot_add_generic(sl, option_byte); + } } /** @@ -3834,20 +4350,19 @@ int stlink_read_option_bytes_boot_add32(stlink_t *sl, uint32_t* option_byte) * @param option_byte option value * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register32(stlink_t *sl, uint32_t* option_byte) -{ - if (sl->option_base == 0) { - ELOG("Option bytes read is currently not supported for connected chip\n"); - return -1; - } +int stlink_read_option_control_register32(stlink_t *sl, uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes read is currently not supported for connected chip\n"); + return -1; + } - switch (sl->chip_id) { - case STLINK_CHIPID_STM32_F7XXXX: - return stlink_read_option_control_register_f7(sl, option_byte); - default: - return -1; - //return stlink_read_option_control_register_generic(sl, option_byte); - } + switch (sl->chip_id) { + case STLINK_CHIPID_STM32_F7XXXX: + return stlink_read_option_control_register_f7(sl, option_byte); + default: + return -1; + // return stlink_read_option_control_register_generic(sl, option_byte); + } } /** @@ -3856,20 +4371,20 @@ int stlink_read_option_control_register32(stlink_t *sl, uint32_t* option_byte) * @param option_byte option value * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register1_32(stlink_t *sl, uint32_t* option_byte) -{ - if (sl->option_base == 0) { - ELOG("Option bytes read is currently not supported for connected chip\n"); - return -1; - } - - switch (sl->chip_id) { - case STLINK_CHIPID_STM32_F7XXXX: - return stlink_read_option_control_register1_f7(sl, option_byte); - default: - return -1; - //return stlink_read_option_control_register1_generic(sl, option_byte); - } +int stlink_read_option_control_register1_32(stlink_t *sl, + uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes read is currently not supported for connected chip\n"); + return -1; + } + + switch (sl->chip_id) { + case STLINK_CHIPID_STM32_F7XXXX: + return stlink_read_option_control_register1_f7(sl, option_byte); + default: + return -1; + // return stlink_read_option_control_register1_generic(sl, option_byte); + } } /** @@ -3878,10 +4393,11 @@ int stlink_read_option_control_register1_32(stlink_t *sl, uint32_t* option_byte) * @param option_byte value to write * @return 0 on success, -ve on failure. */ -int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) -{ - WLOG("About to write option byte %#10x to %#10x.\n", option_byte, sl->option_base); - return stlink_write_option_bytes(sl, sl->option_base, (uint8_t *) &option_byte, 4); +int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) { + WLOG("About to write option byte %#10x to %#10x.\n", option_byte, + sl->option_base); + return stlink_write_option_bytes(sl, sl->option_base, (uint8_t *)&option_byte, + 4); } /** @@ -3891,73 +4407,76 @@ int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) * @param base option bytes to write * @return 0 on success, -ve on failure. */ -int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len) { - int ret = -1; - - if (sl->option_base == 0) { - ELOG("Option bytes writing is currently not supported for connected chip\n"); - return(-1); - } - - - if ((addr < sl->option_base) || addr > sl->option_base + sl->option_size) { - ELOG("Option bytes start address out of Option bytes range\n"); - return(-1); - } - - if (addr + len > sl->option_base + sl->option_size) { - ELOG("Option bytes data too long\n"); - return(-1); - } - - wait_flash_busy(sl); - - if (unlock_flash_if(sl)) { - ELOG("Flash unlock failed! System reset required to be able to unlock it again!\n"); - return(-1); - } - - if (unlock_flash_option_if(sl)) { - ELOG("Flash option unlock failed!\n"); - return(-1); - } - - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F4: - ret = stlink_write_option_bytes_f4(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_F7: - ret = stlink_write_option_bytes_f7(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_L0: - ret = stlink_write_option_bytes_l0(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_L4: - ret = stlink_write_option_bytes_l4(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - ret = stlink_write_option_bytes_gx(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_H7: - ret = stlink_write_option_bytes_h7(sl, base, addr, len); - break; - default: - ELOG("Option bytes writing is currently not implemented for connected chip\n"); - break; - } - - if (ret) { - ELOG("Flash option write failed!\n"); - } else { - ILOG("Wrote %d option bytes to %#010x!\n", len, addr); - } - - /* Re-lock flash. */ - lock_flash_option(sl); - lock_flash(sl); - - return ret; +int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t *base, + uint32_t len) { + int ret = -1; + + if (sl->option_base == 0) { + ELOG( + "Option bytes writing is currently not supported for connected chip\n"); + return (-1); + } + + if ((addr < sl->option_base) || addr > sl->option_base + sl->option_size) { + ELOG("Option bytes start address out of Option bytes range\n"); + return (-1); + } + + if (addr + len > sl->option_base + sl->option_size) { + ELOG("Option bytes data too long\n"); + return (-1); + } + + wait_flash_busy(sl); + + if (unlock_flash_if(sl)) { + ELOG("Flash unlock failed! System reset required to be able to unlock it " + "again!\n"); + return (-1); + } + + if (unlock_flash_option_if(sl)) { + ELOG("Flash option unlock failed!\n"); + return (-1); + } + + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F4: + ret = stlink_write_option_bytes_f4(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_F7: + ret = stlink_write_option_bytes_f7(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_L0: + ret = stlink_write_option_bytes_l0(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_L4: + ret = stlink_write_option_bytes_l4(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + ret = stlink_write_option_bytes_gx(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_H7: + ret = stlink_write_option_bytes_h7(sl, base, addr, len); + break; + default: + ELOG("Option bytes writing is currently not implemented for connected " + "chip\n"); + break; + } + + if (ret) { + ELOG("Flash option write failed!\n"); + } else { + ILOG("Wrote %d option bytes to %#010x!\n", len, addr); + } + + /* Re-lock flash. */ + lock_flash_option(sl); + lock_flash(sl); + + return ret; } /** @@ -3966,23 +4485,30 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, ui * @param option_byte value to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_control_register_f7(stlink_t *sl, uint32_t option_control_register) { - int ret = 0; +static int +stlink_write_option_control_register_f7(stlink_t *sl, + uint32_t option_control_register) { + int ret = 0; - ILOG("Asked to write option control register 1 %#10x to %#010x.\n", option_control_register, FLASH_F7_OPTCR); - //write_uint32((unsigned char*) &option_byte, *(uint32_t*) (base)); - //ILOG("Write %d option bytes %#010x to %#010x!\n", len, option_byte, addr); + // Clear errors + clear_flash_error(sl); - /* write option byte, ensuring we dont lock opt, and set strt bit */ - stlink_write_debug32(sl, FLASH_F7_OPTCR, (option_control_register & ~(1 << FLASH_F7_OPTCR_LOCK)) | (1 << FLASH_F7_OPTCR_START)); + ILOG("Asked to write option control register 1 %#10x to %#010x.\n", + option_control_register, FLASH_F7_OPTCR); - wait_flash_busy(sl); + /* write option byte, ensuring we dont lock opt, and set strt bit */ + stlink_write_debug32(sl, FLASH_F7_OPTCR, + (option_control_register & ~(1 << FLASH_F7_OPTCR_LOCK)) | + (1 << FLASH_F7_OPTCR_START)); - ret = check_flash_error(sl); - if (!ret) - ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register, FLASH_F7_OPTCR1); + wait_flash_busy(sl); - return ret; + ret = check_flash_error(sl); + if (!ret) + ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register, + FLASH_F7_OPTCR); + + return ret; } /** @@ -3991,28 +4517,36 @@ static int stlink_write_option_control_register_f7(stlink_t *sl, uint32_t option * @param option_byte value to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_control_register1_f7(stlink_t *sl, uint32_t option_control_register1) { - int ret = 0; +static int +stlink_write_option_control_register1_f7(stlink_t *sl, + uint32_t option_control_register1) { + int ret = 0; - ILOG("Asked to write option control register 1 %#010x to %#010x.\n", option_control_register1, FLASH_F7_OPTCR1); - //write_uint32((unsigned char*) &option_byte, *(uint32_t*) (base)); - //ILOG("Write %d option bytes %#010x to %#010x!\n", len, option_byte, addr); + // Clear errors + clear_flash_error(sl); - /* write option byte, ensuring we dont lock opt, and set strt bit */ - uint32_t current_control_register_value; - stlink_read_debug32(sl, FLASH_F7_OPTCR, ¤t_control_register_value); + ILOG("Asked to write option control register 1 %#010x to %#010x.\n", + option_control_register1, FLASH_F7_OPTCR1); - /* write option byte */ - stlink_write_debug32(sl, FLASH_F7_OPTCR1, option_control_register1); - stlink_write_debug32(sl, FLASH_F7_OPTCR, (current_control_register_value & ~(1 << FLASH_F7_OPTCR_LOCK)) | (1 << FLASH_F7_OPTCR_START)); + /* write option byte, ensuring we dont lock opt, and set strt bit */ + uint32_t current_control_register_value; + stlink_read_debug32(sl, FLASH_F7_OPTCR, ¤t_control_register_value); - wait_flash_busy(sl); + /* write option byte */ + stlink_write_debug32(sl, FLASH_F7_OPTCR1, option_control_register1); + stlink_write_debug32( + sl, FLASH_F7_OPTCR, + (current_control_register_value & ~(1 << FLASH_F7_OPTCR_LOCK)) | + (1 << FLASH_F7_OPTCR_START)); - ret = check_flash_error(sl); - if (!ret) - ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register1, FLASH_F7_OPTCR1); + wait_flash_busy(sl); - return ret; + ret = check_flash_error(sl); + if (!ret) + ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register1, + FLASH_F7_OPTCR1); + + return ret; } /** @@ -4021,9 +4555,11 @@ static int stlink_write_option_control_register1_f7(stlink_t *sl, uint32_t optio * @param option_byte value to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_boot_add_f7(stlink_t *sl, uint32_t option_byte_boot_add) { - ILOG("Asked to write option byte boot add %#010x.\n", option_byte_boot_add); - return stlink_write_option_control_register1_f7(sl, option_byte_boot_add); +static int +stlink_write_option_bytes_boot_add_f7(stlink_t *sl, + uint32_t option_byte_boot_add) { + ILOG("Asked to write option byte boot add %#010x.\n", option_byte_boot_add); + return stlink_write_option_control_register1_f7(sl, option_byte_boot_add); } /** @@ -4032,41 +4568,43 @@ static int stlink_write_option_bytes_boot_add_f7(stlink_t *sl, uint32_t option_b * @param option bytes boot address to write * @return 0 on success, -ve on failure. */ -int stlink_write_option_bytes_boot_add32(stlink_t *sl, uint32_t option_bytes_boot_add) -{ - int ret = -1; +int stlink_write_option_bytes_boot_add32(stlink_t *sl, + uint32_t option_bytes_boot_add) { + int ret = -1; - wait_flash_busy(sl); + wait_flash_busy(sl); - if (unlock_flash_if(sl)) { - ELOG("Flash unlock failed! System reset required to be able to unlock it again!\n"); - return -1; - } + if (unlock_flash_if(sl)) { + ELOG("Flash unlock failed! System reset required to be able to unlock it " + "again!\n"); + return -1; + } - if (unlock_flash_option_if(sl)) { - ELOG("Flash option unlock failed!\n"); - return -1; - } + if (unlock_flash_option_if(sl)) { + ELOG("Flash option unlock failed!\n"); + return -1; + } - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F7: - ret = stlink_write_option_bytes_boot_add_f7(sl, option_bytes_boot_add); - break; - default: - ELOG("Option bytes boot address writing is currently not implemented for connected chip\n"); - break; - } + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F7: + ret = stlink_write_option_bytes_boot_add_f7(sl, option_bytes_boot_add); + break; + default: + ELOG("Option bytes boot address writing is currently not implemented for " + "connected chip\n"); + break; + } - if (ret) - ELOG("Flash option write failed!\n"); - else - ILOG("Wrote option bytes boot address %#010x!\n", option_bytes_boot_add); + if (ret) + ELOG("Flash option write failed!\n"); + else + ILOG("Wrote option bytes boot address %#010x!\n", option_bytes_boot_add); - /* Re-lock flash. */ - lock_flash_option(sl); - lock_flash(sl); + /* Re-lock flash. */ + lock_flash_option(sl); + lock_flash(sl); - return ret; + return ret; } /** @@ -4075,41 +4613,43 @@ int stlink_write_option_bytes_boot_add32(stlink_t *sl, uint32_t option_bytes_boo * @param option bytes boot address to write * @return 0 on success, -ve on failure. */ -int stlink_write_option_control_register32(stlink_t *sl, uint32_t option_control_register) -{ - int ret = -1; +int stlink_write_option_control_register32(stlink_t *sl, + uint32_t option_control_register) { + int ret = -1; - wait_flash_busy(sl); + wait_flash_busy(sl); - if (unlock_flash_if(sl)) { - ELOG("Flash unlock failed! System reset required to be able to unlock it again!\n"); - return -1; - } + if (unlock_flash_if(sl)) { + ELOG("Flash unlock failed! System reset required to be able to unlock it " + "again!\n"); + return -1; + } - if (unlock_flash_option_if(sl)) { - ELOG("Flash option unlock failed!\n"); - return -1; - } + if (unlock_flash_option_if(sl)) { + ELOG("Flash option unlock failed!\n"); + return -1; + } - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F7: - ret = stlink_write_option_control_register_f7(sl, option_control_register); - break; - default: - ELOG("Option control register writing is currently not implemented for connected chip\n"); - break; - } + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F7: + ret = stlink_write_option_control_register_f7(sl, option_control_register); + break; + default: + ELOG("Option control register writing is currently not implemented for " + "connected chip\n"); + break; + } - if (ret) - ELOG("Flash option write failed!\n"); - else - ILOG("Wrote option control register %#010x!\n", option_control_register); + if (ret) + ELOG("Flash option write failed!\n"); + else + ILOG("Wrote option control register %#010x!\n", option_control_register); - /* Re-lock flash. */ - lock_flash_option(sl); - lock_flash(sl); + /* Re-lock flash. */ + lock_flash_option(sl); + lock_flash(sl); - return ret; + return ret; } /** @@ -4118,40 +4658,43 @@ int stlink_write_option_control_register32(stlink_t *sl, uint32_t option_control * @param option bytes boot address to write * @return 0 on success, -ve on failure. */ -int stlink_write_option_control_register1_32(stlink_t *sl, uint32_t option_control_register1) -{ - int ret = -1; +int stlink_write_option_control_register1_32( + stlink_t *sl, uint32_t option_control_register1) { + int ret = -1; - wait_flash_busy(sl); + wait_flash_busy(sl); - if (unlock_flash_if(sl)) { - ELOG("Flash unlock failed! System reset required to be able to unlock it again!\n"); - return -1; - } + if (unlock_flash_if(sl)) { + ELOG("Flash unlock failed! System reset required to be able to unlock it " + "again!\n"); + return -1; + } - if (unlock_flash_option_if(sl)) { - ELOG("Flash option unlock failed!\n"); - return -1; - } + if (unlock_flash_option_if(sl)) { + ELOG("Flash option unlock failed!\n"); + return -1; + } - switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F7: - ret = stlink_write_option_control_register1_f7(sl, option_control_register1); - break; - default: - ELOG("Option control register 1 writing is currently not implemented for connected chip\n"); - break; - } + switch (sl->flash_type) { + case STLINK_FLASH_TYPE_F7: + ret = + stlink_write_option_control_register1_f7(sl, option_control_register1); + break; + default: + ELOG("Option control register 1 writing is currently not implemented for " + "connected chip\n"); + break; + } - if (ret) - ELOG("Flash option write failed!\n"); - else - ILOG("Wrote option control register 1 %#010x!\n", option_control_register1); + if (ret) + ELOG("Flash option write failed!\n"); + else + ILOG("Wrote option control register 1 %#010x!\n", option_control_register1); - lock_flash_option(sl); - lock_flash(sl); + lock_flash_option(sl); + lock_flash(sl); - return(ret); + return (ret); } /** @@ -4161,24 +4704,66 @@ int stlink_write_option_control_register1_32(stlink_t *sl, uint32_t option_contr * @param addr of the memory mapped option bytes * @return 0 on success, -ve on failure. */ -int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr) { - /* Write the file in flash at addr */ - int err; - mapped_file_t mf = MAPPED_FILE_INITIALIZER; - - if (map_file(&mf, path) == -1) { - ELOG("map_file() == -1\n"); - return(-1); - } +int stlink_fwrite_option_bytes(stlink_t *sl, const char *path, + stm32_addr_t addr) { + /* Write the file in flash at addr */ + int err; + mapped_file_t mf = MAPPED_FILE_INITIALIZER; + + if (map_file(&mf, path) == -1) { + ELOG("map_file() == -1\n"); + return (-1); + } - printf("file %s ", path); - md5_calculate(&mf); - stlink_checksum(&mf); + printf("file %s ", path); + md5_calculate(&mf); + stlink_checksum(&mf); - err = stlink_write_option_bytes(sl, addr, mf.base, (uint32_t)mf.len); - stlink_fwrite_finalize(sl, addr); - unmap_file(&mf); + err = stlink_write_option_bytes(sl, addr, mf.base, (uint32_t)mf.len); + stlink_fwrite_finalize(sl, addr); + unmap_file(&mf); - return(err); + return (err); } +int stlink_target_connect(stlink_t *sl, enum connect_type connect) { + uint32_t dhcsr; + + if (connect == CONNECT_UNDER_RESET) { + stlink_jtag_reset(sl, STLINK_JTAG_DRIVE_NRST_LOW); + + // minimum reset pulse duration of 20 us (RM0008, 8.1.2 Power reset) + usleep(20); + + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { + stlink_enter_swd_mode(sl); + } + stlink_force_debug(sl); + + // clear S_RESET_ST in DHCSR register + stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); + + stlink_jtag_reset(sl, STLINK_JTAG_DRIVE_NRST_HIGH); + usleep(10000); + + // check NRST connection + dhcsr = 0; + stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); + if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) { + WLOG("NRST is not connected\n"); + } + + // addition soft reset for halt before the first instruction + stlink_soft_reset(sl, 1 /* halt on reset */); + } + + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { + stlink_enter_swd_mode(sl); + } + + if (connect == CONNECT_NORMAL) { + stlink_reset(sl, RESET_AUTO); + } + + return stlink_load_device_params(sl); +} diff --git a/src/st-flash/flash.c b/src/st-flash/flash.c index d8bd8772c..ede0f1179 100644 --- a/src/st-flash/flash.c +++ b/src/st-flash/flash.c @@ -17,7 +17,7 @@ static void cleanup(int signum) { (void)signum; if (connected_stlink) { // switch back to mass storage mode before closing - stlink_run(connected_stlink); + stlink_run(connected_stlink, RUN_NORMAL); stlink_exit_debug_mode(connected_stlink); stlink_close(connected_stlink); } @@ -26,9 +26,9 @@ static void cleanup(int signum) { } static void usage(void) { - puts("command line: ./st-flash [--debug] [--reset] [--opt] [--serial ] [--format ] [--flash=] [--freq=] [--area=] {read|write} [path] [addr] [size]"); - puts("command line: ./st-flash [--debug] [--freq=] [--serial ] erase"); - puts("command line: ./st-flash [--debug] [--freq=] [--serial ] reset"); + puts("command line: ./st-flash [--debug] [--reset] [--connect-under-reset] [--hot-plug] [--opt] [--serial ] [--format ] [--flash=] [--freq=] [--area=] {read|write} [path] [addr] [size]"); + puts("command line: ./st-flash [--debug] [--connect-under-reset] [--hot-plug] [--freq=] [--serial ] erase"); + puts("command line: ./st-flash [--debug] [--freq=] [--serial ] reset"); puts(" , and : Use hex format."); puts(" : Use decimal, octal or hex (prefix 0xXXX) format, optionally followed by k=KB, or m=MB (eg. --flash=128k)"); puts(" : Can be 'binary' (default) or 'ihex', although must be specified for binary format only."); @@ -52,6 +52,7 @@ int main(int ac, char** av) { uint8_t * mem = NULL; o.size = 0; + o.connect = CONNECT_NORMAL; if (flash_get_opts(&o, ac - 1, av + 1) == -1) { printf("invalid command line\n"); @@ -61,9 +62,7 @@ int main(int ac, char** av) { printf("st-flash %s\n", STLINK_VERSION); - sl = stlink_open_usb(o.log_level, - o.connect_under_reset ? 2 : 1, - (char *)o.serial, o.freq); + sl = stlink_open_usb(o.log_level, o.connect, (char *)o.serial, o.freq); if (sl == NULL) { return(-1); } @@ -99,33 +98,6 @@ int main(int ac, char** av) { } } - if (o.reset) { - if (sl->version.stlink_v > 1) { - if (stlink_jtag_reset(sl, 2)) { - printf("Failed to reset JTAG\n"); - goto on_error; - } - } - - if (stlink_reset(sl)) { - printf("Failed to reset device\n"); - goto on_error; - } - } - - // disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 - if (sl->chip_id == STLINK_CHIPID_STM32_F4) { - memset(sl->q_buf, 0, 4); - - for (int i = 0; i < 8; i++) { - stlink_write_mem32(sl, 0x40026000 + 0x10 + 0x18 * i, 4); - stlink_write_mem32(sl, 0x40026400 + 0x10 + 0x18 * i, 4); - stlink_write_mem32(sl, 0x40026000 + 0x24 + 0x18 * i, 4); - stlink_write_mem32(sl, 0x40026400 + 0x24 + 0x18 * i, 4); - - } - } - // core must be halted to use RAM based flashloaders if (stlink_force_debug(sl)) { printf("Failed to halt the core\n"); @@ -216,14 +188,7 @@ int main(int ac, char** av) { goto on_error; } } else if (o.cmd == CMD_RESET) { - if (sl->version.stlink_v > 1) { - if (stlink_jtag_reset(sl, 2)) { - printf("Failed to reset JTAG\n"); - goto on_error; - } - } - - if (stlink_reset(sl)) { + if (stlink_reset(sl, RESET_AUTO)) { printf("Failed to reset device\n"); goto on_error; } @@ -291,9 +256,7 @@ int main(int ac, char** av) { } if (o.reset) { - if (sl->version.stlink_v > 1) { stlink_jtag_reset(sl, 2); } - - stlink_reset(sl); + stlink_reset(sl, RESET_AUTO); } err = 0; // success diff --git a/src/st-flash/flash.h b/src/st-flash/flash.h index ca0ca2839..cd08db70f 100644 --- a/src/st-flash/flash.h +++ b/src/st-flash/flash.h @@ -14,7 +14,7 @@ enum flash_format {FLASH_FORMAT_BINARY = 0, FLASH_FORMAT_IHEX = 1}; enum flash_area {FLASH_MAIN_MEMORY = 0, FLASH_SYSTEM_MEMORY = 1, FLASH_OTP = 2, FLASH_OPTION_BYTES = 3, FLASH_OPTION_BYTES_BOOT_ADD = 4, FLASH_OPTCR = 5, FLASH_OPTCR1 = 6}; struct flash_opts { enum flash_cmd cmd; - uint8_t serial[STLINK_SERIAL_MAX_SIZE]; + uint8_t serial[STLINK_SERIAL_BUFFER_SIZE]; const char* filename; stm32_addr_t addr; size_t size; @@ -26,7 +26,7 @@ struct flash_opts { size_t flash_size; // --flash=n[k][m] int opt; // enable empty tail data drop optimization int freq; // --freq=n[k][m] frequency of JTAG/SWD - bool connect_under_reset; + enum connect_type connect; }; #define FLASH_OPTS_INITIALIZER {0, { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} diff --git a/src/st-flash/flash_opts.c b/src/st-flash/flash_opts.c index e74ecc1ce..172a24468 100644 --- a/src/st-flash/flash_opts.c +++ b/src/st-flash/flash_opts.c @@ -2,6 +2,8 @@ #include #include +#include + #include "flash.h" static bool starts_with(const char * str, const char * prefix) { @@ -106,18 +108,8 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av) { serial = av[0] + strlen("--serial="); } - /** @todo This is not really portable, as strlen really returns size_t we need to obey - and not cast it to a signed type. */ - int j = (int)strlen(serial); - int length = j / 2; // the length of the destination-array - - if (j % 2 != 0) { return(-1); } + memcpy(o->serial, serial, STLINK_SERIAL_BUFFER_SIZE); - for (size_t k = 0; j >= 0 && k < sizeof(o->serial); ++k, j -= 2) { - char buffer[3] = {0}; - memcpy(buffer, serial + j, 2); - o->serial[length - k] = (uint8_t)strtol(buffer, NULL, 16); - } } else if (strcmp(av[0], "--area") == 0 || starts_with(av[0], "--area=")) { const char * area; @@ -150,50 +142,21 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av) { return(-1); } - } else if (strcmp(av[0], "--freq") == 0 || starts_with(av[0], "--freq=")) { - const char* freq; - - if (strcmp(av[0], "--freq") == 0) { - ac--; - av++; - - if (ac < 1) { - return(-1); - } + } else if (strcmp(av[0], "--freq") == 0) { + ac--; + av++; - freq = av[0]; - } else { - freq = av[0] + strlen("--freq="); + if (ac < 1) { + return(-1); } - if (strcmp(freq, "5K") == 0 || strcmp(freq, "5k") == 0) { - o->freq = 5; - } else if (strcmp(freq, "15K") == 0 || strcmp(freq, "15k") == 0) { - o->freq = 15; - } else if (strcmp(freq, "25K") == 0 || strcmp(freq, "25k") == 0) { - o->freq = 25; - } else if (strcmp(freq, "50K") == 0 || strcmp(freq, "50k") == 0) { - o->freq = 50; - } else if (strcmp(freq, "100K") == 0 || strcmp(freq, "100k") == 0) { - o->freq = 100; - } else if (strcmp(freq, "125K") == 0 || strcmp(freq, "125k") == 0) { - o->freq = 125; - } else if (strcmp(freq, "240K") == 0 || strcmp(freq, "240k") == 0) { - o->freq = 240; - } else if (strcmp(freq, "480K") == 0 || strcmp(freq, "480k") == 0) { - o->freq = 480; - } else if (strcmp(freq, "950K") == 0 || strcmp(freq, "950k") == 0) { - o->freq = 950; - } else if (strcmp(freq, "1200K") == 0 || strcmp(freq, "1200k") == 0 || - strcmp(freq, "1.2M") == 0 || strcmp(freq, "1.2m") == 0) { - o->freq = 1200; - } else if (strcmp(freq, "1800K") == 0 || strcmp(freq, "1800k") == 0 || - strcmp(freq, "1.8M") == 0 || strcmp(freq, "1.8m") == 0) { - o->freq = 1800; - } else if (strcmp(freq, "4000K") == 0 || strcmp(freq, "4000k") == 0 || - strcmp(freq, "4M") == 0 || strcmp(freq, "4m") == 0) { - o->freq = 4000; - } else { + o->freq = arg_parse_freq(av[0]); + if (o->freq < 0) { + return(-1); + } + } else if (starts_with(av[0], "--freq=")) { + o->freq = arg_parse_freq(av[0] + strlen("--freq=")); + if (o->freq < 0) { return(-1); } } else if (strcmp(av[0], "--format") == 0 || starts_with(av[0], "--format=")) { @@ -229,7 +192,9 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av) { o->flash_size = (size_t)flash_size; } } else if (strcmp(av[0], "--connect-under-reset") == 0) { - o->connect_under_reset = true; + o->connect = CONNECT_UNDER_RESET; + } else if (strcmp(av[0], "--hot-plug") == 0) { + o->connect = CONNECT_HOT_PLUG; } else { break; // non-option found @@ -328,21 +293,14 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av) { case FLASH_CMD_WRITE: // TODO: should be boot add 0 and boot add 1 uint32 - if (o->area == FLASH_OPTION_BYTES) { // expect filename and optional address - if (ac >=1 && ac <= 2) { - o->filename = av[0]; + if (o->area == FLASH_OPTION_BYTES) { // expect option byte value + if (ac != 1) { return invalid_args("option byte write "); } + uint32_t val; + result = get_integer_from_char_array(av[0], &val); + if (result != 0) { + return bad_arg ("val"); } else { - return invalid_args("write [addr]"); - } - - if (ac == 2) { - uint32_t addr; - result = get_integer_from_char_array(av[1], &addr); - if (result != 0) { - return bad_arg ("addr"); - } else { - o->addr = (stm32_addr_t) addr; - } + o->val = (uint32_t) val; } } else if (o->area == FLASH_OPTION_BYTES_BOOT_ADD) { // expect option bytes boot address if (ac != 1) { return invalid_args("option bytes boot_add write "); } diff --git a/src/st-info/info.c b/src/st-info/info.c index 0fc4d4d8a..a6b4e85c6 100644 --- a/src/st-info/info.c +++ b/src/st-info/info.c @@ -4,35 +4,17 @@ #include #include +#include static void usage(void) { puts("st-info --version"); - puts("st-info --probe"); + puts("st-info --probe [--connect-under-reset] [--hot-plug] [--freq=]"); puts("st-info --serial"); - puts("st-info --hla-serial"); - puts("st-info --flash [--connect-under-reset]"); - puts("st-info --pagesize [--connect-under-reset]"); - puts("st-info --sram [--connect-under-reset]"); - puts("st-info --chipid [--connect-under-reset]"); - puts("st-info --descr [--connect-under-reset]"); -} - -/* Print normal or OpenOCD hla_serial with newline */ -static void stlink_print_serial(stlink_t *sl, bool openocd) { - const char *fmt; - - if (openocd) { - printf("\""); - fmt = "\\x%02x"; - } else { - fmt = "%02x"; - } - - for (int n = 0; n < sl->serial_size; n++) { printf(fmt, sl->serial[n]); } - - if (openocd) { printf("\""); } - - printf("\n"); + puts("st-info --flash [--connect-under-reset] [--hot-plug] [--freq=]"); + puts("st-info --pagesize [--connect-under-reset] [--hot-plug] [--freq=]"); + puts("st-info --sram [--connect-under-reset] [--hot-plug] [--freq=]"); + puts("st-info --chipid [--connect-under-reset] [--hot-plug] [--freq=]"); + puts("st-info --descr [--connect-under-reset] [--hot-plug] [--freq=]"); } static void stlink_print_version(stlink_t *sl) { @@ -53,10 +35,7 @@ static void stlink_print_info(stlink_t *sl) { printf(" version: "); stlink_print_version(sl); - printf(" serial: "); - stlink_print_serial(sl, false); - printf(" hla-serial: "); - stlink_print_serial(sl, true); + printf(" serial: %s\n", sl->serial); printf(" flash: %u (pagesize: %u)\n", (uint32_t)sl->flash_size, (uint32_t)sl->flash_pgsz); printf(" sram: %u\n", (uint32_t)sl->sram_size); @@ -67,11 +46,11 @@ static void stlink_print_info(stlink_t *sl) { if (params) { printf(" descr: %s\n", params->description); } } -static void stlink_probe(void) { +static void stlink_probe(enum connect_type connect, int freq) { stlink_t **stdevs; size_t size; - size = stlink_probe_usb(&stdevs); + size = stlink_probe_usb(&stdevs, connect, freq); printf("Found %u stlink programmers\n", (unsigned int)size); @@ -83,44 +62,47 @@ static void stlink_probe(void) { stlink_probe_usb_free(&stdevs, size); } -static stlink_t *stlink_open_first(bool under_reset) { +static int print_data(int ac, char **av) { stlink_t* sl = NULL; - sl = stlink_v1_open(0, 1); + enum connect_type connect = CONNECT_NORMAL; + int freq = 0; - if (sl == NULL) { - if (under_reset) { - sl = stlink_open_usb(0, 2, NULL, 0); - } else { - sl = stlink_open_usb(0, 1, NULL, 0); - } + if (strcmp(av[1], "--version") == 0) { + printf("v%s\n", STLINK_VERSION); + return(0); } - return(sl); -} + for (int i=2; i= 0) { continue; } + } + } else if (strncmp(av[i], "--freq=", 7) == 0) { + freq = arg_parse_freq(av[i] + 7); + if (freq >= 0) { continue; } + } -static int print_data(int ac, char **av) { - stlink_t* sl = NULL; - bool under_reset = false; + printf("Incorrect argument: %s\n\n", av[i]); + usage(); + return(-1); + } // probe needs all devices unclaimed if (strcmp(av[1], "--probe") == 0) { - stlink_probe(); - return(0); - } else if (strcmp(av[1], "--version") == 0) { - printf("v%s\n", STLINK_VERSION); + stlink_probe(connect, freq); return(0); } - if (ac == 3) { - if (strcmp(av[2], "--connect-under-reset") == 0) { - under_reset = true; - } else { - usage(); - return(-1); - } - } - - sl = stlink_open_first(under_reset); + // open first st-link device + sl = stlink_open_usb(0, connect, NULL, freq); if (sl == NULL) { return(-1); } @@ -131,9 +113,7 @@ static int print_data(int ac, char **av) { if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } if (strcmp(av[1], "--serial") == 0) { - stlink_print_serial(sl, false); - } else if (strcmp(av[1], "--hla-serial") == 0) { - stlink_print_serial(sl, true); + printf("%s\n", sl->serial); } else if (strcmp(av[1], "--flash") == 0) { printf("0x%x\n", (uint32_t)sl->flash_size); } else if (strcmp(av[1], "--pagesize") == 0) { diff --git a/src/st-trace/trace.c b/src/st-trace/trace.c index 71ba6b360..a02c64701 100644 --- a/src/st-trace/trace.c +++ b/src/st-trace/trace.c @@ -1,573 +1,596 @@ +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include #include +#include -#include -#include #include - +#include +#include #define DEFAULT_LOGGING_LEVEL 50 #define DEBUG_LOGGING_LEVEL 100 -#define APP_RESULT_SUCCESS 0 -#define APP_RESULT_INVALID_PARAMS 1 -#define APP_RESULT_STLINK_NOT_FOUND 2 -#define APP_RESULT_STLINK_MISSING_DEVICE 3 -#define APP_RESULT_STLINK_UNSUPPORTED_DEVICE 4 -#define APP_RESULT_STLINK_UNSUPPORTED_LINK 5 -#define APP_RESULT_UNSUPPORTED_TRACE_FREQUENCY 6 -#define APP_RESULT_STLINK_STATE_ERROR 7 +#define APP_RESULT_SUCCESS 0 +#define APP_RESULT_INVALID_PARAMS 1 +#define APP_RESULT_STLINK_NOT_FOUND 2 +#define APP_RESULT_STLINK_MISSING_DEVICE 3 +#define APP_RESULT_STLINK_UNSUPPORTED_DEVICE 4 +#define APP_RESULT_STLINK_UNSUPPORTED_LINK 5 +#define APP_RESULT_UNSUPPORTED_TRACE_FREQUENCY 6 +#define APP_RESULT_STLINK_STATE_ERROR 7 // See D4.2 of https://developer.arm.com/documentation/ddi0403/ed/ -#define TRACE_OP_IS_OVERFLOW(c) ((c) == 0x70) -#define TRACE_OP_IS_LOCAL_TIME(c) (((c) & 0x0f) == 0x00 && ((c) & 0x70) != 0x00) -#define TRACE_OP_IS_EXTENSION(c) (((c) & 0x0b) == 0x08) -#define TRACE_OP_IS_GLOBAL_TIME(c) (((c) & 0xdf) == 0x94) -#define TRACE_OP_IS_SOURCE(c) (((c) & 0x03) != 0x00) -#define TRACE_OP_IS_SW_SOURCE(c) (((c) & 0x03) != 0x00 && ((c) & 0x04) == 0x00) -#define TRACE_OP_IS_HW_SOURCE(c) (((c) & 0x03) != 0x00 && ((c) & 0x04) == 0x04) -#define TRACE_OP_IS_TARGET_SOURCE(c) ((c) == 0x01) -#define TRACE_OP_GET_CONTINUATION(c) ((c) & 0x80) -#define TRACE_OP_GET_SOURCE_SIZE(c) ((c) & 0x03) -#define TRACE_OP_GET_SW_SOURCE_ADDR(c) ((c) >> 3) - +#define TRACE_OP_IS_OVERFLOW(c) ((c) == 0x70) +#define TRACE_OP_IS_LOCAL_TIME(c) (((c)&0x0f) == 0x00 && ((c)&0x70) != 0x00) +#define TRACE_OP_IS_EXTENSION(c) (((c)&0x0b) == 0x08) +#define TRACE_OP_IS_GLOBAL_TIME(c) (((c)&0xdf) == 0x94) +#define TRACE_OP_IS_SOURCE(c) (((c)&0x03) != 0x00) +#define TRACE_OP_IS_SW_SOURCE(c) (((c)&0x03) != 0x00 && ((c)&0x04) == 0x00) +#define TRACE_OP_IS_HW_SOURCE(c) (((c)&0x03) != 0x00 && ((c)&0x04) == 0x04) +#define TRACE_OP_IS_TARGET_SOURCE(c) ((c) == 0x01) +#define TRACE_OP_GET_CONTINUATION(c) ((c)&0x80) +#define TRACE_OP_GET_SOURCE_SIZE(c) ((c)&0x03) +#define TRACE_OP_GET_SW_SOURCE_ADDR(c) ((c) >> 3) typedef struct { - bool show_help; - bool show_version; - int logging_level; - uint32_t core_frequency; - uint32_t trace_frequency; - bool reset_board; - bool force; - char* serial_number; + bool show_help; + bool show_version; + int logging_level; + uint32_t core_frequency; + uint32_t trace_frequency; + bool reset_board; + bool force; + char *serial_number; } st_settings_t; - // We use a simple state machine to parse the trace data. typedef enum { - TRACE_STATE_UNKNOWN, - TRACE_STATE_IDLE, - TRACE_STATE_TARGET_SOURCE, - TRACE_STATE_SKIP_FRAME, - TRACE_STATE_SKIP_4, - TRACE_STATE_SKIP_3, - TRACE_STATE_SKIP_2, - TRACE_STATE_SKIP_1, + TRACE_STATE_UNKNOWN, + TRACE_STATE_IDLE, + TRACE_STATE_TARGET_SOURCE, + TRACE_STATE_SKIP_FRAME, + TRACE_STATE_SKIP_4, + TRACE_STATE_SKIP_3, + TRACE_STATE_SKIP_2, + TRACE_STATE_SKIP_1, } trace_state; typedef struct { - time_t start_time; - bool configuration_checked; + time_t start_time; + bool configuration_checked; - trace_state state; + trace_state state; - uint32_t count_raw_bytes; - uint32_t count_target_data; - uint32_t count_time_packets; - uint32_t count_hw_overflow; - uint32_t count_sw_overflow; - uint32_t count_error; + uint32_t count_raw_bytes; + uint32_t count_target_data; + uint32_t count_time_packets; + uint32_t count_hw_overflow; + uint32_t count_sw_overflow; + uint32_t count_error; - uint8_t unknown_opcodes[256 / 8]; - uint32_t unknown_sources; + uint8_t unknown_opcodes[256 / 8]; + uint32_t unknown_sources; } st_trace_t; - -// We use a global flag to allow communicating to the main thread from the signal handler. +// We use a global flag to allow communicating to the main thread from the +// signal handler. static bool g_abort_trace = false; -static void abort_trace() { - g_abort_trace = true; -} +static void abort_trace() { g_abort_trace = true; } #if defined(_WIN32) BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { - (void)fdwCtrlType; - abort_trace(); - return FALSE; + (void)fdwCtrlType; + abort_trace(); + return FALSE; } #endif static void usage(void) { - puts("st-trace - usage:"); - puts(" -h, --help Print this help"); - puts(" -V, --version Print this version"); - puts(" -vXX, --verbose=XX Specify a specific verbosity level (0..99)"); - puts(" -v, --verbose Specify a generally verbose logging"); - puts(" -cXX, --clock=XX Specify the core frequency in MHz"); - puts(" -tXX, --trace=XX Specify the trace frequency in Hz"); - puts(" -n, --no-reset Do not reset board on connection"); - puts(" -sXX, --serial=XX Use a specific serial number"); - puts(" -f, --force Ignore most initialization errors"); + puts("st-trace - usage:"); + puts(" -h, --help Print this help"); + puts(" -V, --version Print this version"); + puts(" -vXX, --verbose=XX Specify a specific verbosity level (0..99)"); + puts(" -v, --verbose Specify a generally verbose logging"); + puts(" -cXX, --clock=XX Specify the core frequency in MHz"); + puts(" -tXX, --trace=XX Specify the trace frequency in Hz"); + puts(" -n, --no-reset Do not reset board on connection"); + puts(" -sXX, --serial=XX Use a specific serial number"); + puts(" -f, --force Ignore most initialization errors"); } -bool parse_options(int argc, char** argv, st_settings_t *settings) { - - static struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", optional_argument, NULL, 'v'}, - {"clock", required_argument, NULL, 'c'}, - {"trace", required_argument, NULL, 't'}, - {"no-reset", no_argument, NULL, 'n'}, - {"serial", required_argument, NULL, 's'}, - {"force", no_argument, NULL, 'f'}, - {0, 0, 0, 0}, - }; - int option_index = 0; - int c; - bool error = false; - - settings->show_help = false; - settings->show_version = false; - settings->logging_level = DEFAULT_LOGGING_LEVEL; - settings->core_frequency = 0; - settings->trace_frequency = 0; - settings->reset_board = true; - settings->force = false; - settings->serial_number = NULL; - ugly_init(settings->logging_level); - - while ((c = getopt_long(argc, argv, "hVv::c:ns:f", long_options, &option_index)) != -1) { - switch (c) { - case 'h': - settings->show_help = true; - break; - case 'V': - settings->show_version = true; - break; - case 'v': - if (optarg) { - settings->logging_level = atoi(optarg); - } else { - settings->logging_level = DEBUG_LOGGING_LEVEL; - } - ugly_init(settings->logging_level); - break; - case 'c': - settings->core_frequency = atoi(optarg) * 1000000; - break; - case 't': - settings->trace_frequency = atoi(optarg); - break; - case 'n': - settings->reset_board = false; - break; - case 'f': - settings->force = true; - break; - case 's': - settings->serial_number = optarg; - break; - case '?': - error = true; - break; - default: - ELOG("Unknown command line option: '%c' (0x%02x)\n", c, c); - error = true; - break; - } +bool parse_options(int argc, char **argv, st_settings_t *settings) { + + static struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", optional_argument, NULL, 'v'}, + {"clock", required_argument, NULL, 'c'}, + {"trace", required_argument, NULL, 't'}, + {"no-reset", no_argument, NULL, 'n'}, + {"serial", required_argument, NULL, 's'}, + {"force", no_argument, NULL, 'f'}, + {0, 0, 0, 0}, + }; + int option_index = 0; + int c; + bool error = false; + + settings->show_help = false; + settings->show_version = false; + settings->logging_level = DEFAULT_LOGGING_LEVEL; + settings->core_frequency = 0; + settings->trace_frequency = 0; + settings->reset_board = true; + settings->force = false; + settings->serial_number = NULL; + ugly_init(settings->logging_level); + + while ((c = getopt_long(argc, argv, "hVv::c:ns:f", long_options, + &option_index)) != -1) { + switch (c) { + case 'h': + settings->show_help = true; + break; + case 'V': + settings->show_version = true; + break; + case 'v': + if (optarg) { + settings->logging_level = atoi(optarg); + } else { + settings->logging_level = DEBUG_LOGGING_LEVEL; + } + ugly_init(settings->logging_level); + break; + case 'c': + settings->core_frequency = atoi(optarg) * 1000000; + break; + case 't': + settings->trace_frequency = atoi(optarg); + break; + case 'n': + settings->reset_board = false; + break; + case 'f': + settings->force = true; + break; + case 's': + settings->serial_number = optarg; + break; + case '?': + error = true; + break; + default: + ELOG("Unknown command line option: '%c' (0x%02x)\n", c, c); + error = true; + break; } + } - if (optind < argc) { - while (optind < argc) { - ELOG("Unknown command line argument: '%s'\n", argv[optind++]); - } - error = true; + if (optind < argc) { + while (optind < argc) { + ELOG("Unknown command line argument: '%s'\n", argv[optind++]); } + error = true; + } - if (error && !settings->force) - return false; + if (error && !settings->force) + return false; - return true; + return true; } -static void convert_serial_number_text_to_binary(const char* text, char binary_out[STLINK_SERIAL_MAX_SIZE]) { - size_t length = 0; - for (uint32_t n = 0; n < strlen(text) && length < STLINK_SERIAL_MAX_SIZE; n += 2) { - char buffer[3] = { 0 }; - memcpy(buffer, text + n, 2); - binary_out[length++] = (uint8_t)strtol(buffer, NULL, 16); - } +static stlink_t *stlink_connect(const st_settings_t *settings) { + return stlink_open_usb(settings->logging_level, false, + settings->serial_number, 0); } -static stlink_t* stlink_connect(const st_settings_t* settings) { - if (settings->serial_number) { - // Open this specific stlink. - char binary_serial_number[STLINK_SERIAL_MAX_SIZE] = { 0 }; - convert_serial_number_text_to_binary(settings->serial_number, binary_serial_number); - return stlink_open_usb(settings->logging_level, false, binary_serial_number, 0); - } else { - // Otherwise, open any stlink. - return stlink_open_usb(settings->logging_level, false, NULL, 0); +static bool enable_trace(stlink_t *stlink, const st_settings_t *settings, + uint32_t trace_frequency) { + + if (stlink_force_debug(stlink)) { + ELOG("Unable to debug device\n"); + if (!settings->force) + return false; + } + + if (settings->reset_board && stlink_reset(stlink, RESET_AUTO)) { + ELOG("Unable to reset device\n"); + if (!settings->force) + return false; + } + + stlink_write_debug32(stlink, STLINK_REG_DHCSR, + STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN | + STLINK_REG_DHCSR_C_HALT); + stlink_write_debug32(stlink, STLINK_REG_DEMCR, STLINK_REG_DEMCR_TRCENA); + stlink_write_debug32(stlink, STLINK_REG_CM3_FP_CTRL, + STLINK_REG_CM3_FP_CTRL_KEY); + stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION0, 0); + stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION1, 0); + stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION2, 0); + stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION3, 0); + stlink_write_debug32(stlink, STLINK_REG_DWT_CTRL, 0); + stlink_write_debug32( + stlink, STLINK_REG_DBGMCU_CR, + STLINK_REG_DBGMCU_CR_DBG_SLEEP | STLINK_REG_DBGMCU_CR_DBG_STOP | + STLINK_REG_DBGMCU_CR_DBG_STANDBY | STLINK_REG_DBGMCU_CR_TRACE_IOEN | + STLINK_REG_DBGMCU_CR_TRACE_MODE_ASYNC); + + if (stlink_trace_enable(stlink, trace_frequency)) { + ELOG("Unable to turn on tracing in stlink\n"); + if (!settings->force) + return false; + } + + stlink_write_debug32(stlink, STLINK_REG_TPI_CSPSR, + STLINK_REG_TPI_CSPSR_PORT_SIZE_1); + + if (settings->core_frequency) { + uint32_t prescaler = settings->core_frequency / trace_frequency - 1; + if (prescaler > STLINK_REG_TPI_ACPR_MAX) { + ELOG("Trace frequency prescaler %d out of range. Try setting a faster " + "trace frequency.\n", + prescaler); + if (!settings->force) + return false; } + stlink_write_debug32(stlink, STLINK_REG_TPI_ACPR, + prescaler); // Set TPIU_ACPR clock divisor + } + stlink_write_debug32(stlink, STLINK_REG_TPI_FFCR, + STLINK_REG_TPI_FFCR_TRIG_IN); + stlink_write_debug32(stlink, STLINK_REG_TPI_SPPR, + STLINK_REG_TPI_SPPR_SWO_NRZ); + stlink_write_debug32(stlink, STLINK_REG_ITM_LAR, STLINK_REG_ITM_LAR_KEY); + stlink_write_debug32(stlink, STLINK_REG_ITM_TCC, + 0x00000400); // Set sync counter + stlink_write_debug32(stlink, STLINK_REG_ITM_TCR, + STLINK_REG_ITM_TCR_TRACE_BUS_ID_1 | + STLINK_REG_ITM_TCR_TS_ENA | + STLINK_REG_ITM_TCR_ITM_ENA); + stlink_write_debug32(stlink, STLINK_REG_ITM_TER, + STLINK_REG_ITM_TER_PORTS_ALL); + stlink_write_debug32(stlink, STLINK_REG_ITM_TPR, + STLINK_REG_ITM_TPR_PORTS_ALL); + stlink_write_debug32(stlink, STLINK_REG_DWT_CTRL, + 4 * STLINK_REG_DWT_CTRL_NUM_COMP | + STLINK_REG_DWT_CTRL_CYC_TAP | + 0xF * STLINK_REG_DWT_CTRL_POST_INIT | + 0xF * STLINK_REG_DWT_CTRL_POST_PRESET | + STLINK_REG_DWT_CTRL_CYCCNT_ENA); + stlink_write_debug32(stlink, STLINK_REG_DEMCR, STLINK_REG_DEMCR_TRCENA); + + uint32_t prescaler; + stlink_read_debug32(stlink, STLINK_REG_TPI_ACPR_MAX, &prescaler); + if (prescaler) { + uint32_t system_clock_speed = (prescaler + 1) * trace_frequency; + uint32_t system_clock_speed_mhz = (system_clock_speed + 500000) / 1000000; + ILOG("Trace Port Interface configured to expect a %d MHz system clock.\n", + system_clock_speed_mhz); + } else { + WLOG("Trace Port Interface not configured. Specify the system clock with " + "a --clock=XX command\n"); + WLOG("line option or set it in your device's clock initialization routine, " + "such as with:\n"); + WLOG(" TPI->ACPR = HAL_RCC_GetHCLKFreq() / %d - 1;\n", trace_frequency); + } + ILOG("Trace frequency set to %d Hz.\n", trace_frequency); + + return true; } -static bool enable_trace(stlink_t* stlink, const st_settings_t* settings, uint32_t trace_frequency) { - - if (stlink_force_debug(stlink)) { - ELOG("Unable to debug device\n"); - if (!settings->force) - return false; - } - - if (settings->reset_board && stlink_jtag_reset(stlink, 2)) { - ELOG("Unable to reset device\n"); - if (!settings->force) - return false; - } - - - stlink_write_debug32(stlink, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | - STLINK_REG_DHCSR_C_DEBUGEN | - STLINK_REG_DHCSR_C_HALT); - stlink_write_debug32(stlink, STLINK_REG_DEMCR, STLINK_REG_DEMCR_TRCENA); - stlink_write_debug32(stlink, STLINK_REG_CM3_FP_CTRL, STLINK_REG_CM3_FP_CTRL_KEY); - stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION0, 0); - stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION1, 0); - stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION2, 0); - stlink_write_debug32(stlink, STLINK_REG_DWT_FUNCTION3, 0); - stlink_write_debug32(stlink, STLINK_REG_DWT_CTRL, 0); - stlink_write_debug32(stlink, STLINK_REG_DBGMCU_CR, STLINK_REG_DBGMCU_CR_DBG_SLEEP | - STLINK_REG_DBGMCU_CR_DBG_STOP | - STLINK_REG_DBGMCU_CR_DBG_STANDBY | - STLINK_REG_DBGMCU_CR_TRACE_IOEN | - STLINK_REG_DBGMCU_CR_TRACE_MODE_ASYNC); - - if (stlink_trace_enable(stlink, trace_frequency)) { - ELOG("Unable to turn on tracing in stlink\n"); - if (!settings->force) - return false; - } - - stlink_write_debug32(stlink, STLINK_REG_TPI_CSPSR, STLINK_REG_TPI_CSPSR_PORT_SIZE_1); - - if (settings->core_frequency) { - uint32_t prescaler = settings->core_frequency / trace_frequency - 1; - if (prescaler > STLINK_REG_TPI_ACPR_MAX) { - ELOG("Trace frequency prescaler %d out of range. Try setting a faster trace frequency.\n", prescaler); - if (!settings->force) - return false; - } - stlink_write_debug32(stlink, STLINK_REG_TPI_ACPR, prescaler); // Set TPIU_ACPR clock divisor - } - stlink_write_debug32(stlink, STLINK_REG_TPI_FFCR, STLINK_REG_TPI_FFCR_TRIG_IN); - stlink_write_debug32(stlink, STLINK_REG_TPI_SPPR, STLINK_REG_TPI_SPPR_SWO_NRZ); - stlink_write_debug32(stlink, STLINK_REG_ITM_LAR, STLINK_REG_ITM_LAR_KEY); - stlink_write_debug32(stlink, STLINK_REG_ITM_TCC, 0x00000400); // Set sync counter - stlink_write_debug32(stlink, STLINK_REG_ITM_TCR, STLINK_REG_ITM_TCR_TRACE_BUS_ID_1 | - STLINK_REG_ITM_TCR_TS_ENA | - STLINK_REG_ITM_TCR_ITM_ENA); - stlink_write_debug32(stlink, STLINK_REG_ITM_TER, STLINK_REG_ITM_TER_PORTS_ALL); - stlink_write_debug32(stlink, STLINK_REG_ITM_TPR, STLINK_REG_ITM_TPR_PORTS_ALL); - stlink_write_debug32(stlink, STLINK_REG_DWT_CTRL, 4 * STLINK_REG_DWT_CTRL_NUM_COMP | - STLINK_REG_DWT_CTRL_CYC_TAP | - 0xF * STLINK_REG_DWT_CTRL_POST_INIT | - 0xF * STLINK_REG_DWT_CTRL_POST_PRESET | - STLINK_REG_DWT_CTRL_CYCCNT_ENA); - stlink_write_debug32(stlink, STLINK_REG_DEMCR, STLINK_REG_DEMCR_TRCENA); - - uint32_t prescaler; - stlink_read_debug32(stlink, STLINK_REG_TPI_ACPR_MAX, &prescaler); - if (prescaler) { - uint32_t system_clock_speed = (prescaler + 1) * trace_frequency; - uint32_t system_clock_speed_mhz = (system_clock_speed + 500000) / 1000000; - ILOG("Trace Port Interface configured to expect a %d MHz system clock.\n", system_clock_speed_mhz); - } else { - WLOG("Trace Port Interface not configured. Specify the system clock with a --clock=XX command\n"); - WLOG("line option or set it in your device's clock initialization routine, such as with:\n"); - WLOG(" TPI->ACPR = HAL_RCC_GetHCLKFreq() / %d - 1;\n", trace_frequency); - } - ILOG("Trace frequency set to %d Hz.\n", trace_frequency); - - return true; +static trace_state update_trace_idle(st_trace_t *trace, uint8_t c) { + // Handle a trace byte when we are in the idle state. + + if (TRACE_OP_IS_TARGET_SOURCE(c)) { + return TRACE_STATE_TARGET_SOURCE; + } + + if (TRACE_OP_IS_SOURCE(c)) { + uint8_t size = TRACE_OP_GET_SOURCE_SIZE(c); + if (TRACE_OP_IS_SW_SOURCE(c)) { + uint8_t addr = TRACE_OP_GET_SW_SOURCE_ADDR(c); + if (!(trace->unknown_sources & (1 << addr))) + WLOG("Unsupported source 0x%x size %d\n", addr, size); + trace->unknown_sources |= (1 << addr); + } + if (size == 1) + return TRACE_STATE_SKIP_1; + if (size == 2) + return TRACE_STATE_SKIP_2; + if (size == 3) + return TRACE_STATE_SKIP_4; + } + + if (TRACE_OP_IS_LOCAL_TIME(c) || TRACE_OP_IS_GLOBAL_TIME(c)) { + trace->count_time_packets++; + return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME + : TRACE_STATE_IDLE; + } + + if (TRACE_OP_IS_EXTENSION(c)) { + return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME + : TRACE_STATE_IDLE; + } + + if (TRACE_OP_IS_OVERFLOW(c)) { + trace->count_hw_overflow++; + } + + if (!(trace->unknown_opcodes[c / 8] & (1 << c % 8))) + WLOG("Unknown opcode 0x%02x\n", c); + trace->unknown_opcodes[c / 8] |= (1 << c % 8); + + trace->count_error++; + return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME + : TRACE_STATE_IDLE; } -static trace_state update_trace_idle(st_trace_t* trace, uint8_t c) { - // Handle a trace byte when we are in the idle state. - - if (TRACE_OP_IS_TARGET_SOURCE(c)) { - return TRACE_STATE_TARGET_SOURCE; - } - - if (TRACE_OP_IS_SOURCE(c)) { - uint8_t size = TRACE_OP_GET_SOURCE_SIZE(c); - if (TRACE_OP_IS_SW_SOURCE(c)) { - uint8_t addr = TRACE_OP_GET_SW_SOURCE_ADDR(c); - if (!(trace->unknown_sources & (1 << addr))) - WLOG("Unsupported source 0x%x size %d\n", addr, size); - trace->unknown_sources |= (1 << addr); - } - if (size == 1) return TRACE_STATE_SKIP_1; - if (size == 2) return TRACE_STATE_SKIP_2; - if (size == 3) return TRACE_STATE_SKIP_4; - } - - if (TRACE_OP_IS_LOCAL_TIME(c) || TRACE_OP_IS_GLOBAL_TIME(c)) { - trace->count_time_packets++; - return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME : TRACE_STATE_IDLE; - } - - if (TRACE_OP_IS_EXTENSION(c)) { - return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME : TRACE_STATE_IDLE; - } +static trace_state update_trace(st_trace_t *trace, uint8_t c) { + trace->count_raw_bytes++; - if (TRACE_OP_IS_OVERFLOW(c)) { - trace->count_hw_overflow++; - } + // Parse the input using a state machine. - if (!(trace->unknown_opcodes[c / 8] & (1 << c % 8))) - WLOG("Unknown opcode 0x%02x\n", c); - trace->unknown_opcodes[c / 8] |= (1 << c % 8); + if (trace->state == TRACE_STATE_UNKNOWN) { + if (TRACE_OP_IS_TARGET_SOURCE(c) || TRACE_OP_IS_LOCAL_TIME(c) || + TRACE_OP_IS_GLOBAL_TIME(c)) + trace->state = TRACE_STATE_IDLE; + } - trace->count_error++; - return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME : TRACE_STATE_IDLE; -} + switch (trace->state) { + case TRACE_STATE_IDLE: + return update_trace_idle(trace, c); -static trace_state update_trace(st_trace_t* trace, uint8_t c) { - trace->count_raw_bytes++; + case TRACE_STATE_TARGET_SOURCE: + putchar(c); + if (c == '\n') + fflush(stdout); + trace->count_target_data++; + return TRACE_STATE_IDLE; - // Parse the input using a state machine. + case TRACE_STATE_SKIP_FRAME: + return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME + : TRACE_STATE_IDLE; - if (trace->state == TRACE_STATE_UNKNOWN) { - if (TRACE_OP_IS_TARGET_SOURCE(c) || TRACE_OP_IS_LOCAL_TIME(c) || TRACE_OP_IS_GLOBAL_TIME(c)) - trace->state = TRACE_STATE_IDLE; - } + case TRACE_STATE_SKIP_4: + return TRACE_STATE_SKIP_3; - switch (trace->state) - { - case TRACE_STATE_IDLE: - return update_trace_idle(trace, c); + case TRACE_STATE_SKIP_3: + return TRACE_STATE_SKIP_2; - case TRACE_STATE_TARGET_SOURCE: - putchar(c); - if (c == '\n') - fflush(stdout); - trace->count_target_data++; - return TRACE_STATE_IDLE; + case TRACE_STATE_SKIP_2: + return TRACE_STATE_SKIP_1; - case TRACE_STATE_SKIP_FRAME: - return TRACE_OP_GET_CONTINUATION(c) ? TRACE_STATE_SKIP_FRAME : TRACE_STATE_IDLE; + case TRACE_STATE_SKIP_1: + return TRACE_STATE_IDLE; - case TRACE_STATE_SKIP_4: - return TRACE_STATE_SKIP_3; + case TRACE_STATE_UNKNOWN: + return TRACE_STATE_UNKNOWN; - case TRACE_STATE_SKIP_3: - return TRACE_STATE_SKIP_2; - - case TRACE_STATE_SKIP_2: - return TRACE_STATE_SKIP_1; - - case TRACE_STATE_SKIP_1: - return TRACE_STATE_IDLE; - - case TRACE_STATE_UNKNOWN: - return TRACE_STATE_UNKNOWN; - - default: - ELOG("Invalid state %d. This should never happen\n", trace->state); - return TRACE_STATE_IDLE; - } + default: + ELOG("Invalid state %d. This should never happen\n", trace->state); + return TRACE_STATE_IDLE; + } } -static bool read_trace(stlink_t* stlink, st_trace_t* trace) { - uint8_t buffer[STLINK_TRACE_BUF_LEN]; - int length = stlink_trace_read(stlink, buffer, sizeof(buffer)); +static bool read_trace(stlink_t *stlink, st_trace_t *trace) { + uint8_t buffer[STLINK_TRACE_BUF_LEN]; + int length = stlink_trace_read(stlink, buffer, sizeof(buffer)); - if (length < 0) { - ELOG("Error reading trace (%d)\n", length); - return false; - } - - if (length == 0) { - usleep(100); - return true; - } - - if (length == sizeof(buffer)) { - if (trace->count_sw_overflow++) - DLOG("Buffer overflow.\n"); - else - WLOG("Buffer overflow. Try using a slower trace frequency.\n"); - trace->state = TRACE_STATE_UNKNOWN; - } - - for (int i = 0; i < length; i++) { - trace->state = update_trace(trace, buffer[i]); - } + if (length < 0) { + ELOG("Error reading trace (%d)\n", length); + return false; + } + if (length == 0) { + usleep(100); return true; -} - -static void check_for_configuration_error(stlink_t* stlink, st_trace_t* trace, uint32_t trace_frequency) { - // Only check configuration one time after the first 10 seconds of running. - time_t elapsed_time_s = time(NULL) - trace->start_time; - if (trace->configuration_checked || elapsed_time_s < 10) { - return; - } - trace->configuration_checked = true; - - // Simple huristic to determine if we are configured poorly. - bool error_no_data = (trace->count_raw_bytes < 100); - bool error_low_data = (trace->count_time_packets < 10 && trace->count_target_data < 1000); - bool error_bad_data = (trace->count_error > 1 || trace->unknown_sources > 0); - bool error_dropped_data = (trace->count_sw_overflow > 0); - - if (!error_no_data && !error_low_data && !error_bad_data && !error_dropped_data) - return; + } - WLOG("****\n"); - WLOG("We do not appear to be retrieving data from the stlink correctly.\n"); + if (length == sizeof(buffer)) { + if (trace->count_sw_overflow++) + DLOG("Buffer overflow.\n"); + else + WLOG("Buffer overflow. Try using a slower trace frequency.\n"); + trace->state = TRACE_STATE_UNKNOWN; + } - if (error_dropped_data) { - WLOG("Try setting a slower trace frequency with the --trace=%d command line option.\n", trace_frequency / 2); - } + for (int i = 0; i < length; i++) { + trace->state = update_trace(trace, buffer[i]); + } - if (error_no_data || error_low_data || error_bad_data) { - uint32_t prescaler; - stlink_read_debug32(stlink, STLINK_REG_TPI_ACPR, &prescaler); - if (prescaler) { - uint32_t system_clock_speed = (prescaler + 1) * trace_frequency; - uint32_t system_clock_speed_mhz = (system_clock_speed + 500000) / 1000000; - WLOG("Verify the system clock is running at %d MHz.\n", system_clock_speed_mhz); - } - WLOG("Try specifying the system clock with the --clock=XX command line option.\n"); - WLOG("Try setting the trace speed in your device's clock initialization routine:\n"); - WLOG(" TPI->ACPR = HAL_RCC_GetHCLKFreq() / %d - 1;\n", trace_frequency); - } + return true; +} - WLOG("Diagnostic Information:\n"); - WLOG("Raw Bytes: %d\n", trace->count_raw_bytes); - WLOG("Target Data: %d\n", trace->count_target_data); - WLOG("Time Packets: %d\n", trace->count_time_packets); - WLOG("Hardware Overflow Count: %d\n", trace->count_hw_overflow); - WLOG("Software Overflow Count: %d\n", trace->count_sw_overflow); - WLOG("Errors: %d\n", trace->count_error); - - char buffer[1024]; - memset(buffer, 0, sizeof(buffer)); - uint32_t offset = 0; - for (uint32_t i = 0; i <= 0xFF; i++) - if (trace->unknown_opcodes[i / 8] & (1 << i % 8)) - offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%02x, ", i); - WLOG("Unknown Opcodes: %s\n", buffer); - - memset(buffer, 0, sizeof(buffer)); - offset = 0; - for (uint32_t i = 0; i < 32; i++) - if (trace->unknown_sources & (1 << i)) - offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d, ", i); - WLOG("Unknown Sources: %s\n", buffer); - - WLOG("Chip ID: 0x%04x\n", stlink->chip_id); - WLOG("****\n"); +static void check_for_configuration_error(stlink_t *stlink, st_trace_t *trace, + uint32_t trace_frequency) { + // Only check configuration one time after the first 10 seconds of running. + time_t elapsed_time_s = time(NULL) - trace->start_time; + if (trace->configuration_checked || elapsed_time_s < 10) { + return; + } + trace->configuration_checked = true; + + // Simple huristic to determine if we are configured poorly. + bool error_no_data = (trace->count_raw_bytes < 100); + bool error_low_data = + (trace->count_time_packets < 10 && trace->count_target_data < 1000); + bool error_bad_data = (trace->count_error > 1 || trace->unknown_sources > 0); + bool error_dropped_data = (trace->count_sw_overflow > 0); + + if (!error_no_data && !error_low_data && !error_bad_data && + !error_dropped_data) + return; + + WLOG("****\n"); + WLOG("We do not appear to be retrieving data from the stlink correctly.\n"); + + if (error_dropped_data) { + WLOG("Try setting a slower trace frequency with the --trace=%d command " + "line option.\n", + trace_frequency / 2); + } + + if (error_no_data || error_low_data || error_bad_data) { + uint32_t prescaler; + stlink_read_debug32(stlink, STLINK_REG_TPI_ACPR, &prescaler); + if (prescaler) { + uint32_t system_clock_speed = (prescaler + 1) * trace_frequency; + uint32_t system_clock_speed_mhz = (system_clock_speed + 500000) / 1000000; + WLOG("Verify the system clock is running at %d MHz.\n", + system_clock_speed_mhz); + } + WLOG("Try specifying the system clock with the --clock=XX command line " + "option.\n"); + WLOG("Try setting the trace speed in your device's clock initialization " + "routine:\n"); + WLOG(" TPI->ACPR = HAL_RCC_GetHCLKFreq() / %d - 1;\n", trace_frequency); + } + + WLOG("Diagnostic Information:\n"); + WLOG("Raw Bytes: %d\n", trace->count_raw_bytes); + WLOG("Target Data: %d\n", trace->count_target_data); + WLOG("Time Packets: %d\n", trace->count_time_packets); + WLOG("Hardware Overflow Count: %d\n", trace->count_hw_overflow); + WLOG("Software Overflow Count: %d\n", trace->count_sw_overflow); + WLOG("Errors: %d\n", trace->count_error); + + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + uint32_t offset = 0; + for (uint32_t i = 0; i <= 0xFF; i++) + if (trace->unknown_opcodes[i / 8] & (1 << i % 8)) { + uint32_t n = + snprintf(buffer + offset, sizeof(buffer) - offset, "%02x, ", i); + if (n >= sizeof(buffer) - offset) { + break; + } + offset += n; + } + WLOG("Unknown Opcodes: %s\n", buffer); + + memset(buffer, 0, sizeof(buffer)); + offset = 0; + for (uint32_t i = 0; i < 32; i++) + if (trace->unknown_sources & (1 << i)) { + uint32_t n = + snprintf(buffer + offset, sizeof(buffer) - offset, "%d, ", i); + if (n >= sizeof(buffer) - offset) { + break; + } + offset += n; + } + WLOG("Unknown Sources: %s\n", buffer); + + WLOG("Chip ID: 0x%04x\n", stlink->chip_id); + WLOG("****\n"); } -int main(int argc, char** argv) -{ +int main(int argc, char **argv) { #if defined(_WIN32) - SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); + SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); #else - signal(SIGINT, &abort_trace); - signal(SIGTERM, &abort_trace); - signal(SIGSEGV, &abort_trace); - signal(SIGPIPE, &abort_trace); + signal(SIGINT, &abort_trace); + signal(SIGTERM, &abort_trace); + signal(SIGSEGV, &abort_trace); + signal(SIGPIPE, &abort_trace); #endif + st_settings_t settings; + if (!parse_options(argc, argv, &settings)) { + usage(); + return APP_RESULT_INVALID_PARAMS; + } + + DLOG("show_help = %s\n", settings.show_help ? "true" : "false"); + DLOG("show_version = %s\n", settings.show_version ? "true" : "false"); + DLOG("logging_level = %d\n", settings.logging_level); + DLOG("core_frequency = %d Hz\n", settings.core_frequency); + DLOG("trace_frequency = %d Hz\n", settings.trace_frequency); + DLOG("reset_board = %s\n", settings.reset_board ? "true" : "false"); + DLOG("force = %s\n", settings.force ? "true" : "false"); + DLOG("serial_number = %s\n", + settings.serial_number ? settings.serial_number : "any"); + + if (settings.show_help) { + usage(); + return APP_RESULT_SUCCESS; + } - st_settings_t settings; - if (!parse_options(argc, argv, &settings)) { - usage(); - return APP_RESULT_INVALID_PARAMS; - } - - DLOG("show_help = %s\n", settings.show_help ? "true" : "false"); - DLOG("show_version = %s\n", settings.show_version ? "true" : "false"); - DLOG("logging_level = %d\n", settings.logging_level); - DLOG("core_frequency = %d Hz\n", settings.core_frequency); - DLOG("trace_frequency = %d Hz\n", settings.trace_frequency); - DLOG("reset_board = %s\n", settings.reset_board ? "true" : "false"); - DLOG("force = %s\n", settings.force ? "true" : "false"); - DLOG("serial_number = %s\n", settings.serial_number ? settings.serial_number : "any"); - - if (settings.show_help) { - usage(); - return APP_RESULT_SUCCESS; - } - - if (settings.show_version) { - printf("v%s\n", STLINK_VERSION); - return APP_RESULT_SUCCESS; - } - - stlink_t* stlink = stlink_connect(&settings); - if (!stlink) { - ELOG("Unable to locate an stlink\n"); - return APP_RESULT_STLINK_NOT_FOUND; - } - - stlink->verbose = settings.logging_level; - - if (stlink->chip_id == STLINK_CHIPID_UNKNOWN) { - ELOG("Your stlink is not connected to a device\n"); - if (!settings.force) - return APP_RESULT_STLINK_MISSING_DEVICE; - } - - if (!(stlink->version.flags & STLINK_F_HAS_TRACE)) { - ELOG("Your stlink does not support tracing\n"); - if (!settings.force) - return APP_RESULT_STLINK_UNSUPPORTED_LINK; - } - - if (!(stlink->chip_flags & CHIP_F_HAS_SWO_TRACING)) { - const struct stlink_chipid_params *params = stlink_chipid_get_params(stlink->chip_id); - ELOG("We do not support SWO output for device '%s'\n", params->description); - if (!settings.force) - return APP_RESULT_STLINK_UNSUPPORTED_DEVICE; - } - - uint32_t trace_frequency = settings.trace_frequency; - if (!trace_frequency) - trace_frequency = STLINK_DEFAULT_TRACE_FREQUENCY; - if (trace_frequency > stlink->max_trace_freq) { - ELOG("Invalid trace frequency %d (max %d)\n", trace_frequency, stlink->max_trace_freq); - if (!settings.force) - return APP_RESULT_UNSUPPORTED_TRACE_FREQUENCY; - } - - if (!enable_trace(stlink, &settings, trace_frequency)) { - ELOG("Unable to enable trace mode\n"); - if (!settings.force) - return APP_RESULT_STLINK_STATE_ERROR; - } - - ILOG("Reading Trace\n"); - st_trace_t trace; - memset(&trace, 0, sizeof(trace)); - trace.start_time = time(NULL); - - if (stlink_run(stlink)) { - ELOG("Unable to run device\n"); - if (!settings.force) - return APP_RESULT_STLINK_STATE_ERROR; - } - - while (!g_abort_trace && read_trace(stlink, &trace)) { - check_for_configuration_error(stlink, &trace, trace_frequency); - } - - stlink_trace_disable(stlink); - stlink_close(stlink); - + if (settings.show_version) { + printf("v%s\n", STLINK_VERSION); return APP_RESULT_SUCCESS; + } + + stlink_t *stlink = stlink_connect(&settings); + if (!stlink) { + ELOG("Unable to locate an stlink\n"); + return APP_RESULT_STLINK_NOT_FOUND; + } + + stlink->verbose = settings.logging_level; + + if (stlink->chip_id == STLINK_CHIPID_UNKNOWN) { + ELOG("Your stlink is not connected to a device\n"); + if (!settings.force) + return APP_RESULT_STLINK_MISSING_DEVICE; + } + + if (!(stlink->version.flags & STLINK_F_HAS_TRACE)) { + ELOG("Your stlink does not support tracing\n"); + if (!settings.force) + return APP_RESULT_STLINK_UNSUPPORTED_LINK; + } + + if (!(stlink->chip_flags & CHIP_F_HAS_SWO_TRACING)) { + const struct stlink_chipid_params *params = + stlink_chipid_get_params(stlink->chip_id); + ELOG("We do not support SWO output for device '%s'\n", params->description); + if (!settings.force) + return APP_RESULT_STLINK_UNSUPPORTED_DEVICE; + } + + uint32_t trace_frequency = settings.trace_frequency; + if (!trace_frequency) + trace_frequency = STLINK_DEFAULT_TRACE_FREQUENCY; + if (trace_frequency > stlink->max_trace_freq) { + ELOG("Invalid trace frequency %d (max %d)\n", trace_frequency, + stlink->max_trace_freq); + if (!settings.force) + return APP_RESULT_UNSUPPORTED_TRACE_FREQUENCY; + } + + if (!enable_trace(stlink, &settings, trace_frequency)) { + ELOG("Unable to enable trace mode\n"); + if (!settings.force) + return APP_RESULT_STLINK_STATE_ERROR; + } + + ILOG("Reading Trace\n"); + st_trace_t trace; + memset(&trace, 0, sizeof(trace)); + trace.start_time = time(NULL); + + if (stlink_run(stlink, RUN_NORMAL)) { + ELOG("Unable to run device\n"); + if (!settings.force) + return APP_RESULT_STLINK_STATE_ERROR; + } + + while (!g_abort_trace && read_trace(stlink, &trace)) { + check_for_configuration_error(stlink, &trace, trace_frequency); + } + + stlink_trace_disable(stlink); + stlink_close(stlink); + + return APP_RESULT_SUCCESS; } diff --git a/src/st-util/gdb-server.c b/src/st-util/gdb-server.c index 4177cef11..006a0e3aa 100644 --- a/src/st-util/gdb-server.c +++ b/src/st-util/gdb-server.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include "gdb-remote.h" #include "gdb-server.h" @@ -41,9 +42,6 @@ #define FLASH_PAGE (sl->flash_pgsz) static stlink_t *connected_stlink = NULL; -static bool semihosting = false; -static bool serial_specified = false; -static char serialnumber[STLINK_SERIAL_MAX_SIZE] = {0}; #if defined(_WIN32) #define close_socket win32_close_socket @@ -56,14 +54,16 @@ static char serialnumber[STLINK_SERIAL_MAX_SIZE] = {0}; static const char hex[] = "0123456789abcdef"; -static const char* current_memory_map = NULL; - typedef struct _st_state_t { // things from command line, bleh int logging_level; int listen_port; int persistent; - int reset; + enum connect_type connect_mode; + int freq; + char serialnumber[STLINK_SERIAL_BUFFER_SIZE]; + bool semihosting; + const char* current_memory_map; } st_state_t; @@ -74,7 +74,7 @@ static void init_cache(stlink_t *sl); static void _cleanup() { if (connected_stlink) { // Switch back to mass storage mode before closing - stlink_run(connected_stlink); + stlink_run(connected_stlink, RUN_NORMAL); stlink_exit_debug_mode(connected_stlink); stlink_close(connected_stlink); } @@ -95,20 +95,6 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { } #endif - -static stlink_t* do_connect(st_state_t *st) { - stlink_t *sl = NULL; - - if (serial_specified) { - sl = stlink_open_usb(st->logging_level, st->reset, serialnumber, 0); - } else { - sl = stlink_open_usb(st->logging_level, st->reset, NULL, 0); - } - - return(sl); -} - - int parse_options(int argc, char** argv, st_state_t *st) { static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, @@ -116,6 +102,9 @@ int parse_options(int argc, char** argv, st_state_t *st) { {"listen_port", required_argument, NULL, 'p'}, {"multi", optional_argument, NULL, 'm'}, {"no-reset", optional_argument, NULL, 'n'}, + {"hot-plug", optional_argument, NULL, 'n'}, + {"connect-under-reset", optional_argument, NULL, 'u'}, + {"freq", optional_argument, NULL, 'F'}, {"version", no_argument, NULL, 'V'}, {"semihosting", no_argument, NULL, SEMIHOSTING_OPTION}, {"serial", required_argument, NULL, SERIAL_OPTION}, @@ -126,16 +115,18 @@ int parse_options(int argc, char** argv, st_state_t *st) { " -V, --version\t\tPrint the version\n" " -vXX, --verbose=XX\tSpecify a specific verbosity level (0..99)\n" " -v, --verbose\t\tSpecify generally verbose logging\n" - "\t\t\tChoose what version of stlink to use, (defaults to 2)\n" - " -1, --stlinkv1\tForce stlink version 1\n" " -p 4242, --listen_port=1234\n" "\t\t\tSet the gdb server listen port. " "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n" " -m, --multi\n" "\t\t\tSet gdb server to extended mode.\n" "\t\t\tst-util will continue listening for connections after disconnect.\n" - " -n, --no-reset\n" + " -n, --no-reset, --hot-plug\n" "\t\t\tDo not reset board on connection.\n" + " -u, --connect-under-reset\n" + "\t\t\tConnect to the board before executing any instructions.\n" + " -F 1800K, --freq=1M\n" + "\t\t\tSet the frequency of the SWD/JTAG interface.\n" " --semihosting\n" "\t\t\tEnable semihosting support.\n" " --serial \n" @@ -160,7 +151,6 @@ int parse_options(int argc, char** argv, st_state_t *st) { exit(EXIT_SUCCESS); break; case 'v': - if (optarg) { st->logging_level = atoi(optarg); } else { @@ -170,7 +160,6 @@ int parse_options(int argc, char** argv, st_state_t *st) { break; case 'p': sscanf(optarg, "%i", &q); - if (q < 0) { fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); exit(EXIT_FAILURE); @@ -178,35 +167,32 @@ int parse_options(int argc, char** argv, st_state_t *st) { st->listen_port = q; break; + case 'm': - st->persistent = 1; + st->persistent = true; break; case 'n': - st->reset = 0; + st->connect_mode = CONNECT_HOT_PLUG; + break; + case 'u': + st->connect_mode = CONNECT_UNDER_RESET; + break; + case 'F': + st->freq = arg_parse_freq(optarg); + if (st->freq < 0) { + fprintf(stderr, "Can't parse a frequency: %s\n", optarg); + exit(EXIT_FAILURE); + } break; case 'V': printf("v%s\n", STLINK_VERSION); exit(EXIT_SUCCESS); case SEMIHOSTING_OPTION: - semihosting = true; + st->semihosting = true; break; case SERIAL_OPTION: printf("use serial %s\n", optarg); - /* TODO: This is not really portable, as strlen really returns size_t, - * we need to obey and not cast it to a signed type. - */ - int j = (int)strlen(optarg); - int length = j / 2; // the length of the destination-array - - if (j % 2 != 0) { return(-1); } - - for (size_t k = 0; j >= 0 && k < sizeof(serialnumber); ++k, j -= 2) { - char buffer[3] = {0}; - memcpy(buffer, optarg + j, 2); - serialnumber[length - k] = (uint8_t)strtol(buffer, NULL, 16); - } - - serial_specified = true; + memcpy(st->serialnumber, optarg, STLINK_SERIAL_BUFFER_SIZE); break; } @@ -230,13 +216,12 @@ int main(int argc, char** argv) { // set defaults ... state.logging_level = DEFAULT_LOGGING_LEVEL; state.listen_port = DEFAULT_GDB_LISTEN_PORT; - state.reset = 1; // by default, reset board + state.connect_mode = CONNECT_NORMAL; // by default, reset board parse_options(argc, argv, &state); printf("st-util\n"); - sl = do_connect(&state); - + sl = stlink_open_usb(state.logging_level, state.connect_mode, state.serialnumber, state.freq); if (sl == NULL) { return(1); } if (sl->chip_id == STLINK_CHIPID_UNKNOWN) { @@ -244,7 +229,9 @@ int main(int argc, char** argv) { return(1); } + sl->verbose = 0; connected_stlink = sl; + #if defined(_WIN32) SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE); #else @@ -253,27 +240,19 @@ int main(int argc, char** argv) { signal(SIGSEGV, &cleanup); #endif - if (state.reset) { stlink_reset(sl); } - DLOG("Chip ID is %#010x, Core ID is %#08x.\n", sl->chip_id, sl->core_id); - sl->verbose = 0; - current_memory_map = make_memory_map(sl); - #if defined(_WIN32) WSADATA wsadata; if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) { goto winsock_error; } - #endif - init_cache(sl); - - do { // don't go beserk if serve() returns with error + do { // don't go beserk if serve() returns with error if (serve(sl, &state)) { usleep (1 * 1000); } - sl = connected_stlink; // in case serve() changed the connection - stlink_run(sl); // continue + sl = connected_stlink; // in case serve() changed the connection + stlink_run(sl, RUN_NORMAL); // continue } while (state.persistent); #if defined(_WIN32) @@ -288,7 +267,7 @@ int main(int argc, char** argv) { return(0); } -static const char* const target_description_F4 = +static const char* const target_description = "" "" "" @@ -817,10 +796,11 @@ static int flash_add_block(stm32_addr_t addr, unsigned length, stlink_t *sl) { } struct flash_block* new = malloc(sizeof(struct flash_block)); - new->next = flash_root; + new->next = flash_root; new->addr = addr; new->length = length; - new->data = calloc(length, 1); + new->data = malloc(length); + memset(new->data, stlink_get_erased_pattern(sl), length); flash_root = new; return(0); @@ -867,16 +847,13 @@ static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) { return(0); } -static int flash_go(stlink_t *sl) { +static int flash_go(stlink_t *sl, st_state_t *st) { int error = -1; int ret; flash_loader_t fl; - // some kinds of clock settings do not allow writing to flash. - stlink_reset(sl); + stlink_target_connect(sl, st->connect_mode); stlink_force_debug(sl); - // delay to ensure that STM32 HSI clock and others have started up fully - usleep(10000); for (struct flash_block* fb = flash_root; fb; fb = fb->next) { ILOG("flash_erase: block %08x -> %04x\n", fb->addr, fb->length); @@ -910,8 +887,8 @@ static int flash_go(stlink_t *sl) { } } - stlink_flashloader_stop(sl); - stlink_soft_reset(sl, 1 /* halt on reset */); + stlink_flashloader_stop(sl, &fl); + stlink_reset(sl, RESET_SOFT_AND_HALT); error = 0; error: @@ -1121,13 +1098,22 @@ int serve(stlink_t *sl, st_state_t *st) { close_socket(sock); + uint32_t chip_id = sl->chip_id; + + stlink_target_connect(sl, st->connect_mode); stlink_force_debug(sl); - if (st->reset) { stlink_reset(sl); } + if (sl->chip_id != chip_id) { + WLOG("Target has changed!\n"); + } init_code_breakpoints(sl); init_data_watchpoints(sl); + init_cache(sl); + + st->current_memory_map = make_memory_map(sl); + ILOG("GDB connected.\n"); /* @@ -1178,13 +1164,7 @@ int serve(stlink_t *sl, st_state_t *st) { DLOG("query: %s;%s\n", queryName, params); if (!strcmp(queryName, "Supported")) { - if (sl->chip_id == STLINK_CHIPID_STM32_F4 || - sl->chip_id == STLINK_CHIPID_STM32_F4_HD || - sl->core_id == STM32F7_CORE_ID) { - reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+"); - } else { - reply = strdup("PacketSize=3fff;qXfer:memory-map:read+"); - } + reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+"); } else if (!strcmp(queryName, "Xfer")) { char *type, *op, *__s_addr, *s_length; char *tok = params; @@ -1202,14 +1182,15 @@ int serve(stlink_t *sl, st_state_t *st) { DLOG("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n", type, op, annex, addr, length); - const char* data = NULL; - - if (!strcmp(type, "memory-map") && !strcmp(op, "read")) { - data = current_memory_map; - } - - if (!strcmp(type, "features") && !strcmp(op, "read")) { - data = target_description_F4; + const char* data; + if (strcmp(op, "read")) { + data = NULL; + } else if (!strcmp(type, "memory-map")) { + data = st->current_memory_map; + } else if (!strcmp(type, "features")) { + data = target_description; + } else { + data = NULL; } if (data) { @@ -1254,7 +1235,7 @@ int serve(stlink_t *sl, st_state_t *st) { if (!strncmp(cmd, "resume", 6)) { // resume DLOG("Rcmd: resume\n"); cache_sync(sl); - ret = stlink_run(sl); + ret = stlink_run(sl, RUN_NORMAL); if (ret) { DLOG("Rcmd: resume failed\n"); @@ -1276,22 +1257,14 @@ int serve(stlink_t *sl, st_state_t *st) { } else if (!strncmp(cmd, "jtag_reset", 10)) { // jtag_reset reply = strdup("OK"); - ret = stlink_jtag_reset(sl, 0); - - if (ret) { - DLOG("Rcmd: jtag_reset failed with jtag_reset\n"); - reply = strdup("E00"); - } - - ret = stlink_jtag_reset(sl, 1); + ret = stlink_reset(sl, RESET_HARD); if (ret) { DLOG("Rcmd: jtag_reset failed with jtag_reset\n"); reply = strdup("E00"); } ret = stlink_force_debug(sl); - if (ret) { DLOG("Rcmd: jtag_reset failed with force_debug\n"); reply = strdup("E00"); @@ -1304,14 +1277,12 @@ int serve(stlink_t *sl, st_state_t *st) { } else if (!strncmp(cmd, "reset", 5)) { // reset ret = stlink_force_debug(sl); - if (ret) { DLOG("Rcmd: reset failed with force_debug\n"); reply = strdup("E00"); } - ret = stlink_reset(sl); - + ret = stlink_reset(sl, RESET_AUTO); if (ret) { DLOG("Rcmd: reset failed with reset\n"); reply = strdup("E00"); @@ -1332,10 +1303,10 @@ int serve(stlink_t *sl, st_state_t *st) { while (isspace(*arg)) { arg++; } // skip whitespaces if (!strncmp(arg, "enable", 6) || !strncmp(arg, "1", 1)) { - semihosting = true; + st->semihosting = true; reply = strdup("OK"); } else if (!strncmp(arg, "disable", 7) || !strncmp(arg, "0", 1)) { - semihosting = false; + st->semihosting = false; reply = strdup("OK"); } else { DLOG("Rcmd: unknown semihosting arg: '%s'\n", arg); @@ -1414,7 +1385,7 @@ int serve(stlink_t *sl, st_state_t *st) { free(decoded); } else if (!strcmp(cmdName, "FlashDone")) { - if (flash_go(sl)) { + if (flash_go(sl, st)) { reply = strdup("E08"); } else { reply = strdup("OK"); @@ -1431,7 +1402,7 @@ int serve(stlink_t *sl, st_state_t *st) { case 'c': cache_sync(sl); - ret = stlink_run(sl); + ret = stlink_run(sl, RUN_NORMAL); if (ret) { DLOG("Semihost: run failed\n"); } @@ -1460,7 +1431,7 @@ int serve(stlink_t *sl, st_state_t *st) { int offset = 0; uint16_t insn; - if (!semihosting) { break; } + if (!st->semihosting) { break; } ret = stlink_read_all_regs (sl, ®); @@ -1501,7 +1472,7 @@ int serve(stlink_t *sl, st_state_t *st) { // continue execution cache_sync(sl); - ret = stlink_run(sl); + ret = stlink_run(sl, RUN_NORMAL); if (ret) { DLOG("Semihost: continue execution failed with stlink_run\n"); } } else { @@ -1592,7 +1563,7 @@ int serve(stlink_t *sl, st_state_t *st) { reply = strdup("E00"); } - if (ret) { DLOG("p packet: stlink_read_unsupported_reg failed with id %u\n", id); } + if (ret) { DLOG("p packet: could not read register with id %u\n", id); } if (reply == NULL) { // if reply is set to "E00", skip @@ -1828,7 +1799,7 @@ int serve(stlink_t *sl, st_state_t *st) { case 'R': { // reset the core. - ret = stlink_reset(sl); + ret = stlink_reset(sl, RESET_AUTO); if (ret) { DLOG("R packet : stlink_reset failed\n"); } init_code_breakpoints(sl); @@ -1841,26 +1812,20 @@ int serve(stlink_t *sl, st_state_t *st) { } case 'k': // kill request - reset the connection itself - ret = stlink_run(sl); - + ret = stlink_run(sl, RUN_NORMAL); if (ret) { DLOG("Kill: stlink_run failed\n"); } ret = stlink_exit_debug_mode(sl); - if (ret) { DLOG("Kill: stlink_exit_debug_mode failed\n"); } stlink_close(sl); - sl = do_connect(st); - + sl = stlink_open_usb(st->logging_level, st->connect_mode, st->serialnumber, st->freq); if (sl == NULL || sl->chip_id == STLINK_CHIPID_UNKNOWN) { cleanup(0); } connected_stlink = sl; - if (st->reset) { stlink_reset(sl); } - ret = stlink_force_debug(sl); - if (ret) { DLOG("Kill: stlink_force_debug failed\n"); } init_cache(sl); diff --git a/src/stlink-gui/gui.c b/src/stlink-gui/gui.c index ed38fcc7c..03e999b7f 100644 --- a/src/stlink-gui/gui.c +++ b/src/stlink-gui/gui.c @@ -489,7 +489,6 @@ static void stlink_gui_set_connected(STlinkGUI *gui) { static void connect_button_cb(GtkWidget *widget, gpointer data) { STlinkGUI *gui; - gint i; (void)widget; gui = STLINK_GUI(data); @@ -514,18 +513,6 @@ static void connect_button_cb(GtkWidget *widget, gpointer data) { stlink_enter_swd_mode(gui->sl); } - // disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 - if (gui->sl->chip_id == STLINK_CHIPID_STM32_F4) { - memset(gui->sl->q_buf, 0, 4); - - for (i = 0; i < 8; i++) { - stlink_write_mem32(gui->sl, 0x40026000 + 0x10 + 0x18 * i, 4); - stlink_write_mem32(gui->sl, 0x40026400 + 0x10 + 0x18 * i, 4); - stlink_write_mem32(gui->sl, 0x40026000 + 0x24 + 0x18 * i, 4); - stlink_write_mem32(gui->sl, 0x40026400 + 0x24 + 0x18 * i, 4); - } - } - stlink_gui_set_connected(gui); } diff --git a/src/stlink-lib/chipid.c b/src/stlink-lib/chipid.c index 221234bbb..187a6d957 100644 --- a/src/stlink-lib/chipid.c +++ b/src/stlink-lib/chipid.c @@ -7,12 +7,15 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F7XXXX, .description = "F76xxx", .flash_type = STLINK_FLASH_TYPE_F7, - .flash_size_reg = 0x1ff0f442, // section 45.2 - .flash_pagesize = 0x800, // No flash pages - .sram_size = 0x80000, // "SRAM" byte size in hex from - .bootrom_base = 0x00200000, // ! "System memory" starting address from - .bootrom_size = 0xEDC0, // ! @todo "System memory" byte size in hex from - .option_base = STM32_F7_OPTION_BYTES_BASE, // Used for reading back the option bytes, writing uses FLASH_F7_OPTCR and FLASH_F7_OPTCR1 + .flash_size_reg = 0x1ff0f442, // section 45.2 + .flash_pagesize = 0x800, // No flash pages + .sram_size = 0x80000, // "SRAM" byte size in hex from + .bootrom_base = 0x00200000, // ! "System memory" starting address from + .bootrom_size = 0xEDC0, // ! @todo "System memory" byte size in hex from + .option_base = + STM32_F7_OPTION_BYTES_BASE, // Used for reading back the option + // bytes, writing uses FLASH_F7_OPTCR + // and FLASH_F7_OPTCR1 .option_size = 0x20, .flags = CHIP_F_HAS_SWO_TRACING, }, @@ -21,11 +24,13 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F7, .description = "F7xx", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1ff0f442, // section 41.2 - .flash_pagesize = 0x800, // No flash pages - .sram_size = 0x50000, // "SRAM" byte size in hex from DS Fig 18 - .bootrom_base = 0x00100000, // "System memory" starting address from DS Fig 18 - .bootrom_size = 0xEDC0, // "System memory" byte size in hex from DS Fig 18 + .flash_size_reg = 0x1ff0f442, // section 41.2 + .flash_pagesize = 0x800, // No flash pages + .sram_size = 0x50000, // "SRAM" byte size in hex from DS Fig 18 + .bootrom_base = + 0x00100000, // "System memory" starting address from DS Fig 18 + .bootrom_size = + 0xEDC0, // "System memory" byte size in hex from DS Fig 18 .flags = CHIP_F_HAS_SWO_TRACING, }, { @@ -33,14 +38,17 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F72XXX, .description = "F72x/F73x", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1ff07a22, // section 35.2 - .flash_pagesize = 0x800, // No flash pages - .sram_size = 0x40000, // "SRAM" byte size in hex from DS Fig 24 - .bootrom_base = 0x00100000, // "System memory" starting address from DS Fig 24 - .bootrom_size = 0xEDC0, // "System memory" byte size in hex from DS Fig 24 + .flash_size_reg = 0x1ff07a22, // section 35.2 + .flash_pagesize = 0x800, // No flash pages + .sram_size = 0x40000, // "SRAM" byte size in hex from DS Fig 24 + .bootrom_base = + 0x00100000, // "System memory" starting address from DS Fig 24 + .bootrom_size = + 0xEDC0, // "System memory" byte size in hex from DS Fig 24 .flags = CHIP_F_HAS_SWO_TRACING, }, - { // table 2, PM0063 + { + // table 2, PM0063 .chip_id = STLINK_CHIPID_STM32_F1_MEDIUM, .description = "F1xx Medium-density", .flash_type = STLINK_FLASH_TYPE_F0, @@ -51,11 +59,12 @@ static const struct stlink_chipid_params devices[] = { .bootrom_size = 0x800, .flags = CHIP_F_HAS_SWO_TRACING, }, - { // table 1, PM0059 + { + // table 1, PM0059 .chip_id = STLINK_CHIPID_STM32_F2, .description = "F2xx", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1fff7a22, // as in RM0033 Rev 5 + .flash_size_reg = 0x1fff7a22, // as in RM0033 Rev 5 .flash_pagesize = 0x20000, .sram_size = 0x20000, .bootrom_base = 0x1fff0000, @@ -64,7 +73,8 @@ static const struct stlink_chipid_params devices[] = { .option_size = 4, .flags = CHIP_F_HAS_SWO_TRACING, }, - { // PM0063 + { + // PM0063 .chip_id = STLINK_CHIPID_STM32_F1_LOW, .description = "F1 Low-density device", .flash_type = STLINK_FLASH_TYPE_F0, @@ -79,7 +89,7 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F4, .description = "F4xx", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 + .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 .flash_pagesize = 0x4000, .sram_size = 0x30000, .bootrom_base = 0x1fff0000, @@ -92,7 +102,7 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F4_DSI, .description = "F46x/F47x", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 + .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 .flash_pagesize = 0x4000, .sram_size = 0x40000, .bootrom_base = 0x1fff0000, @@ -103,7 +113,7 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F4_HD, .description = "F42x/F43x", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 + .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 .flash_pagesize = 0x4000, .sram_size = 0x40000, .bootrom_base = 0x1fff0000, @@ -224,7 +234,8 @@ static const struct stlink_chipid_params devices[] = { .bootrom_size = 0x4800, .flags = CHIP_F_HAS_SWO_TRACING, }, - { // Low and Medium density VL have same chipid. RM0041 25.6.1 + { + // Low and Medium density VL have same chipid. RM0041 25.6.1 .chip_id = STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW, .description = "F1xx Value Line", .flash_type = STLINK_FLASH_TYPE_F0, @@ -315,11 +326,12 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F0_CAN, .description = "F07x", .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x800, // Page sizes listed in Table 4 - .sram_size = 0x4000, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffC800, // "System memory" starting address from Table 2 - .bootrom_size = 0x3000, // "System memory" byte size in hex from Table 2 + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x800, // Page sizes listed in Table 4 + .sram_size = 0x4000, // "SRAM" byte size in hex from Table 2 + .bootrom_base = + 0x1fffC800, // "System memory" starting address from Table 2 + .bootrom_size = 0x3000, // "System memory" byte size in hex from Table 2 }, { // Use this as an example for mapping future chips: @@ -327,11 +339,12 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F0, .description = "F0xx", .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x400, // Page sizes listed in Table 4 - .sram_size = 0x2000, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 - .bootrom_size = 0xC00, // "System memory" byte size in hex from Table 2 + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x400, // Page sizes listed in Table 4 + .sram_size = 0x2000, // "SRAM" byte size in hex from Table 2 + .bootrom_base = + 0x1fffec00, // "System memory" starting address from Table 2 + .bootrom_size = 0xC00, // "System memory" byte size in hex from Table 2 }, { // RM0402 document was used to find these parameters @@ -339,11 +352,12 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F412, .description = "F412", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, // "Flash size data register" (pg1135) - .flash_pagesize = 0x4000, // Table 5. Flash module organization ? - .sram_size = 0x40000, // "SRAM" byte size in hex from Table 4 - .bootrom_base = 0x1FFF0000, // "System memory" starting address from Table 4 - .bootrom_size = 0x7800, // "System memory" byte size in hex from Table 4 + .flash_size_reg = 0x1FFF7A22, // "Flash size data register" (pg1135) + .flash_pagesize = 0x4000, // Table 5. Flash module organization ? + .sram_size = 0x40000, // "SRAM" byte size in hex from Table 4 + .bootrom_base = + 0x1FFF0000, // "System memory" starting address from Table 4 + .bootrom_size = 0x7800, // "System memory" byte size in hex from Table 4 .flags = CHIP_F_HAS_SWO_TRACING, }, { @@ -352,22 +366,27 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F413, .description = "F413", .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, // "Flash size data register" Section 35.2 - .flash_pagesize = 0x4000, // Table 5. Flash module organization (variable sector sizes, but 0x4000 is smallest) - .sram_size = 0x50000, // "SRAM" byte size in hex from Figure 2 (Table 4 only says 0x40000) - .bootrom_base = 0x1FFF0000, // "System memory" starting address from Table 4 - .bootrom_size = 0x7800, // "System memory" byte size in hex from Table 4 + .flash_size_reg = 0x1FFF7A22, // "Flash size data register" Section 35.2 + .flash_pagesize = + 0x4000, // Table 5. Flash module organization (variable sector + // sizes, but 0x4000 is smallest) + .sram_size = 0x50000, // "SRAM" byte size in hex from Figure 2 (Table 4 + // only says 0x40000) + .bootrom_base = + 0x1FFF0000, // "System memory" starting address from Table 4 + .bootrom_size = 0x7800, // "System memory" byte size in hex from Table 4 .flags = CHIP_F_HAS_SWO_TRACING, }, { .chip_id = STLINK_CHIPID_STM32_F09X, .description = "F09X", .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x800, // Page sizes listed in Table 4 (pg 56) - .sram_size = 0x8000, // "SRAM" byte size in hex from Table 2 (pg 50) - .bootrom_base = 0x1fffd800, // "System memory" starting address from Table 2 - .bootrom_size = 0x2000, // "System memory" byte size in hex from Table 2 + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x800, // Page sizes listed in Table 4 (pg 56) + .sram_size = 0x8000, // "SRAM" byte size in hex from Table 2 (pg 50) + .bootrom_base = + 0x1fffd800, // "System memory" starting address from Table 2 + .bootrom_size = 0x2000, // "System memory" byte size in hex from Table 2 }, { // Use this as an example for mapping future chips: @@ -375,11 +394,12 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F04, .description = "F04x", .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x400, // Page sizes listed in Table 4 - .sram_size = 0x1800, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 - .bootrom_size = 0xC00, // "System memory" byte size in hex from Table 2 + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x400, // Page sizes listed in Table 4 + .sram_size = 0x1800, // "SRAM" byte size in hex from Table 2 + .bootrom_base = + 0x1fffec00, // "System memory" starting address from Table 2 + .bootrom_size = 0xC00, // "System memory" byte size in hex from Table 2 }, { // Use this as an example for mapping future chips: @@ -387,11 +407,12 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F0_SMALL, .description = "F0xx small", .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x400, // Page sizes listed in Table 4 - .sram_size = 0x1000, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 - .bootrom_size = 0xC00, // "System memory" byte size in hex from Table 2 + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x400, // Page sizes listed in Table 4 + .sram_size = 0x1000, // "SRAM" byte size in hex from Table 2 + .bootrom_base = + 0x1fffec00, // "System memory" starting address from Table 2 + .bootrom_size = 0xC00, // "System memory" byte size in hex from Table 2 }, { // STM32F30x @@ -416,7 +437,7 @@ static const struct stlink_chipid_params devices[] = { .sram_size = 0x2000, .bootrom_base = 0x1ff0000, .bootrom_size = 0x1000, - .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, + .option_base = STM32_L0_OPTION_BYTES_BASE, .option_size = 20, }, { @@ -430,7 +451,7 @@ static const struct stlink_chipid_params devices[] = { .sram_size = 0x5000, .bootrom_base = 0x1ff0000, .bootrom_size = 0x2000, - .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, + .option_base = STM32_L0_OPTION_BYTES_BASE, .option_size = 20, }, { @@ -444,7 +465,7 @@ static const struct stlink_chipid_params devices[] = { .sram_size = 0x2000, .bootrom_base = 0x1ff0000, .bootrom_size = 0x1000, - .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, + .option_base = STM32_L0_OPTION_BYTES_BASE, .option_size = 20, }, { @@ -466,10 +487,10 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_F303_HIGH, .description = "F303 high density", .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // 34.2.1 Flash size data register - .flash_pagesize = 0x800, // 4.2.1 Flash memory organization - .sram_size = 0x10000, // 3.3 Embedded SRAM - .bootrom_base = 0x1fffd800, // 3.3.2 / Table 4 System Memory + .flash_size_reg = 0x1ffff7cc, // 34.2.1 Flash size data register + .flash_pagesize = 0x800, // 4.2.1 Flash memory organization + .sram_size = 0x10000, // 3.3 Embedded SRAM + .bootrom_base = 0x1fffd800, // 3.3.2 / Table 4 System Memory .bootrom_size = 0x2000, .flags = CHIP_F_HAS_SWO_TRACING, }, @@ -479,15 +500,18 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_L4, .description = "L4xx", .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1FFF75e0, // "Flash size data register" (sec 45.2, page 1671) - .flash_pagesize = 0x800, // 2k (sec 3.2, page 78; also appears in sec 3.3.1 - // and tables 4-6 on pages 79-81) - // SRAM1 is "up to" 96k in the standard Cortex-M memory map; - // SRAM2 is 32k mapped at at 0x10000000 (sec 2.3, page 73 for - // sizes; table 2, page 74 for SRAM2 location) + .flash_size_reg = + 0x1FFF75e0, // "Flash size data register" (sec 45.2, page 1671) + .flash_pagesize = + 0x800, // 2k (sec 3.2, page 78; also appears in sec 3.3.1 + // and tables 4-6 on pages 79-81) + // SRAM1 is "up to" 96k in the standard Cortex-M memory map; + // SRAM2 is 32k mapped at at 0x10000000 (sec 2.3, page 73 for + // sizes; table 2, page 74 for SRAM2 location) .sram_size = 0x18000, - .bootrom_base = 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) - .bootrom_size = 0x7000, // 28k (per bank), same source as base + .bootrom_base = + 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) + .bootrom_size = 0x7000, // 28k (per bank), same source as base .option_base = STM32_L4_OPTION_BYTES_BASE, .option_size = 4, .flags = CHIP_F_HAS_SWO_TRACING, @@ -498,11 +522,13 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_L4RX, .description = "L4Rx", .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 52.2, page 2049) - .flash_pagesize = 0x1000, // 4k, section 3.3, pg 97 - .sram_size = 0xa0000, // 192k (SRAM1) + 64k SRAM2 + 384k SRAM3 = 640k, or 0xA0000 - .bootrom_base = 0x1fff0000, // 3.3.1, pg 99 - .bootrom_size = 0x7000, // 28k (per bank), same source as base (pg 99) + .flash_size_reg = + 0x1fff75e0, // "Flash size data register" (sec 52.2, page 2049) + .flash_pagesize = 0x1000, // 4k, section 3.3, pg 97 + .sram_size = + 0xa0000, // 192k (SRAM1) + 64k SRAM2 + 384k SRAM3 = 640k, or 0xA0000 + .bootrom_base = 0x1fff0000, // 3.3.1, pg 99 + .bootrom_size = 0x7000, // 28k (per bank), same source as base (pg 99) .flags = CHIP_F_HAS_SWO_TRACING, }, { @@ -511,13 +537,16 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_L41X, .description = "L41x", .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (RM0394, sec 47.2, page 1586) - .flash_pagesize = 0x800, // 2k (DS12469, sec 3.4, page 17) - // SRAM1 is 32k at 0x20000000 - // SRAM2 is 8k at 0x10000000 and 0x20008000 (DS12469, sec 3.5, page 18) - .sram_size = 0xa000, // 40k (DS12469, sec 3.5, page 18) - .bootrom_base = 0x1fff0000, // System Memory (RM0394, sec 3.3.1, table 8) - .bootrom_size = 0x7000, // 28k, same source as base + .flash_size_reg = 0x1fff75e0, // "Flash size data register" (RM0394, + // sec 47.2, page 1586) + .flash_pagesize = 0x800, // 2k (DS12469, sec 3.4, page 17) + // SRAM1 is 32k at 0x20000000 + // SRAM2 is 8k at 0x10000000 and 0x20008000 + // (DS12469, sec 3.5, page 18) + .sram_size = 0xa000, // 40k (DS12469, sec 3.5, page 18) + .bootrom_base = + 0x1fff0000, // System Memory (RM0394, sec 3.3.1, table 8) + .bootrom_size = 0x7000, // 28k, same source as base .flags = CHIP_F_HAS_SWO_TRACING, }, { @@ -526,15 +555,18 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_L43X, .description = "L43x/L44x", .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 43.2, page 1410) - .flash_pagesize = 0x800, // 2k (sec 3.2, page 74; also appears in sec 3.3.1 - // and tables 7-8 on pages 75-76) - // SRAM1 is "up to" 64k in the standard Cortex-M memory map; - // SRAM2 is 16k mapped at 0x10000000 (sec 2.3, page 73 for - // sizes; table 2, page 74 for SRAM2 location) + .flash_size_reg = + 0x1fff75e0, // "Flash size data register" (sec 43.2, page 1410) + .flash_pagesize = + 0x800, // 2k (sec 3.2, page 74; also appears in sec 3.3.1 + // and tables 7-8 on pages 75-76) + // SRAM1 is "up to" 64k in the standard Cortex-M memory map; + // SRAM2 is 16k mapped at 0x10000000 (sec 2.3, page 73 for + // sizes; table 2, page 74 for SRAM2 location) .sram_size = 0xc000, - .bootrom_base = 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) - .bootrom_size = 0x7000, // 28k (per bank), same source as base + .bootrom_base = + 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) + .bootrom_size = 0x7000, // 28k (per bank), same source as base .option_base = STM32_L4_OPTION_BYTES_BASE, .option_size = 4, .flags = CHIP_F_HAS_SWO_TRACING, @@ -545,13 +577,15 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_L496X, .description = "L496x/L4A6x", .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 49.2, page 1809) - .flash_pagesize = 0x800, // Page erase (2 Kbyte) (sec 3.2, page 93) - // SRAM1 is 256k at 0x20000000 - // SRAM2 is 64k at 0x20040000 (sec 2.2.1, fig 2, page 74) - .sram_size = 0x40000, // Embedded SRAM (sec 2.4, page 84) - .bootrom_base = 0x1fff0000, // System Memory (Bank 1) (sec 3.3.1) - .bootrom_size = 0x7000, // 28k (per bank), same source as base + .flash_size_reg = + 0x1fff75e0, // "Flash size data register" (sec 49.2, page 1809) + .flash_pagesize = + 0x800, // Page erase (2 Kbyte) (sec 3.2, page 93) + // SRAM1 is 256k at 0x20000000 + // SRAM2 is 64k at 0x20040000 (sec 2.2.1, fig 2, page 74) + .sram_size = 0x40000, // Embedded SRAM (sec 2.4, page 84) + .bootrom_base = 0x1fff0000, // System Memory (Bank 1) (sec 3.3.1) + .bootrom_size = 0x7000, // 28k (per bank), same source as base .option_base = STM32_L4_OPTION_BYTES_BASE, .option_size = 4, .flags = CHIP_F_HAS_SWO_TRACING, @@ -562,14 +596,18 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_L46X, .description = "L45x/46x", .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 45.2, page 1463) - .flash_pagesize = 0x800, // 2k (sec 3.2, page 73; also appears in sec 3.3.1 - // and tables 7 on pages 73-74) - // SRAM1 is 128k at 0x20000000; - // SRAM2 is 32k mapped at 0x10000000 (sec 2.4.2, table 3-4, page 68, also fig 2 on page 63) + .flash_size_reg = + 0x1fff75e0, // "Flash size data register" (sec 45.2, page 1463) + .flash_pagesize = + 0x800, // 2k (sec 3.2, page 73; also appears in sec 3.3.1 + // and tables 7 on pages 73-74) + // SRAM1 is 128k at 0x20000000; + // SRAM2 is 32k mapped at 0x10000000 (sec 2.4.2, table 3-4, + // page 68, also fig 2 on page 63) .sram_size = 0x20000, - .bootrom_base = 0x1fff0000, // Tables 6, pages 71-72 (Bank 1 system memory, also fig 2 on page 63) - .bootrom_size = 0x7000, // 28k (per bank), same source as base + .bootrom_base = 0x1fff0000, // Tables 6, pages 71-72 (Bank 1 system + // memory, also fig 2 on page 63) + .bootrom_size = 0x7000, // 28k (per bank), same source as base .flags = CHIP_F_HAS_SWO_TRACING, }, { @@ -588,11 +626,11 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_G0_CAT1, .description = "G030/G031/G041", .flash_type = STLINK_FLASH_TYPE_G0, - .flash_size_reg = 0x1FFF75E0, // Section 38.2 - .flash_pagesize = 0x800, // 2k (sec 3.2) - .sram_size = 0x2000, // 8k (sec 2.3) + .flash_size_reg = 0x1FFF75E0, // Section 38.2 + .flash_pagesize = 0x800, // 2k (sec 3.2) + .sram_size = 0x2000, // 8k (sec 2.3) .bootrom_base = 0x1fff0000, - .bootrom_size = 0x2000, // 8k (sec 2.2.2 table 3) + .bootrom_size = 0x2000, // 8k (sec 2.2.2 table 3) .option_base = STM32_G0_OPTION_BYTES_BASE, .option_size = 4, }, @@ -601,11 +639,11 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_G0_CAT2, .description = "G070/G071/G081", .flash_type = STLINK_FLASH_TYPE_G0, - .flash_size_reg = 0x1FFF75E0, // Section 38.2 - .flash_pagesize = 0x800, // 2k (sec 3.2) - .sram_size = 0x9000, // 36k (sec 2.3) + .flash_size_reg = 0x1FFF75E0, // Section 38.2 + .flash_pagesize = 0x800, // 2k (sec 3.2) + .sram_size = 0x9000, // 36k (sec 2.3) .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7000, // 28k (sec 2.2.2 table 2) + .bootrom_size = 0x7000, // 28k (sec 2.2.2 table 2) .option_base = STM32_G0_OPTION_BYTES_BASE, .option_size = 4, }, @@ -614,14 +652,15 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_G4_CAT2, .description = "G4 Category-2", .flash_type = STLINK_FLASH_TYPE_G4, - .flash_size_reg = 0x1FFF75E0, // Section 47.2 - .flash_pagesize = 0x800, // 2k (sec 3.3.1) - // SRAM1 is 16k at 0x20000000 - // SRAM2 is 6k at 0x20014000 - // SRAM3/CCM is 10k at 0x10000000, aliased at 0x20018000 - .sram_size = 0x8000, // 32k (sec 2.4) + .flash_size_reg = 0x1FFF75E0, // Section 47.2 + .flash_pagesize = + 0x800, // 2k (sec 3.3.1) + // SRAM1 is 16k at 0x20000000 + // SRAM2 is 6k at 0x20014000 + // SRAM3/CCM is 10k at 0x10000000, aliased at 0x20018000 + .sram_size = 0x8000, // 32k (sec 2.4) .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7000, // 28k (table 2) + .bootrom_size = 0x7000, // 28k (table 2) .option_base = STM32_G4_OPTION_BYTES_BASE, .option_size = 4, .flags = CHIP_F_HAS_SWO_TRACING, @@ -631,14 +670,15 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_G4_CAT3, .description = "G4 Category-3", .flash_type = STLINK_FLASH_TYPE_G4, - .flash_size_reg = 0x1FFF75E0, // Section 47.2 - .flash_pagesize = 0x800, // 2k (sec 3.3.1) - // SRAM1 is 80k at 0x20000000 - // SRAM2 is 16k at 0x20014000 - // SRAM3/CCM is 32k at 0x10000000, aliased at 0x20018000 - .sram_size = 0x18000, // 128k (sec 2.4) + .flash_size_reg = 0x1FFF75E0, // Section 47.2 + .flash_pagesize = + 0x800, // 2k (sec 3.3.1) + // SRAM1 is 80k at 0x20000000 + // SRAM2 is 16k at 0x20014000 + // SRAM3/CCM is 32k at 0x10000000, aliased at 0x20018000 + .sram_size = 0x18000, // 128k (sec 2.4) .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7000, // 28k (table 2) + .bootrom_size = 0x7000, // 28k (table 2) .option_base = STM32_G4_OPTION_BYTES_BASE, .option_size = 4, .flags = CHIP_F_HAS_DUAL_BANK | CHIP_F_HAS_SWO_TRACING, @@ -649,7 +689,7 @@ static const struct stlink_chipid_params devices[] = { .description = "WB55", .flash_type = STLINK_FLASH_TYPE_WB, .flash_size_reg = 0x1FFF75E0, - .flash_pagesize = 0x1000, // 4k + .flash_pagesize = 0x1000, // 4k .sram_size = 0x40000, .bootrom_base = 0x1fff0000, // see the memory map .bootrom_size = 0x7000, @@ -660,13 +700,15 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_H74XXX, .description = "H74x/H75x", .flash_type = STLINK_FLASH_TYPE_H7, - .flash_size_reg = 0x1ff1e880, // "Flash size register" (pg3272) - .flash_pagesize = 0x20000, // 128k sector (pg147) - .sram_size = 0x20000, // 128k "DTCM" from Table 7 - .bootrom_base = 0x1ff00000, // "System memory" starting address from Table 7 - .bootrom_size = 0x20000, // "System memory" byte size in hex from Table 7 + .flash_size_reg = 0x1ff1e880, // "Flash size register" (pg3272) + .flash_pagesize = 0x20000, // 128k sector (pg147) + .sram_size = 0x20000, // 128k "DTCM" from Table 7 + .bootrom_base = + 0x1ff00000, // "System memory" starting address from Table 7 + .bootrom_size = + 0x20000, // "System memory" byte size in hex from Table 7 .option_base = STM32_H7_OPTION_BYTES_BASE, - .option_size = 44, // FLASH_OPTSR_CUR to FLASH_BOOT_PRGR from Table 28 + .option_size = 44, // FLASH_OPTSR_CUR to FLASH_BOOT_PRGR from Table 28 .flags = CHIP_F_HAS_DUAL_BANK | CHIP_F_HAS_SWO_TRACING, }, { @@ -674,11 +716,13 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_H7AX, .description = "H7Ax/H7Bx", .flash_type = STLINK_FLASH_TYPE_H7, - .flash_size_reg = 0x08FFF80C, // "Flash size register" (p.2949) - .flash_pagesize = 0x2000, // 8k sector (p.146) - .sram_size = 0x20000, // 128k "DTCM" (Figure 1) - .bootrom_base = 0x1FF00000, // "System memory" starting address (Table 12-14) - .bootrom_size = 0x20000, // "System memory" byte size in hex splitted to two banks (Table 12-14) + .flash_size_reg = 0x08FFF80C, // "Flash size register" (p.2949) + .flash_pagesize = 0x2000, // 8k sector (p.146) + .sram_size = 0x20000, // 128k "DTCM" (Figure 1) + .bootrom_base = + 0x1FF00000, // "System memory" starting address (Table 12-14) + .bootrom_size = 0x20000, // "System memory" byte size in hex splitted to + // two banks (Table 12-14) .option_base = STM32_H7_OPTION_BYTES_BASE, .option_size = 44, .flags = CHIP_F_HAS_DUAL_BANK | CHIP_F_HAS_SWO_TRACING, @@ -688,11 +732,12 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_H72X, .description = "H72x/H73x", .flash_type = STLINK_FLASH_TYPE_H7, - .flash_size_reg = 0x1FF1E880, // "Flash size register" (p.3286) - .flash_pagesize = 0x20000, // 128k sector (p.152) - .sram_size = 0x20000, // 128k "DTCM" (Figure 1) - .bootrom_base = 0x1FF00000, // "System memory" starting address (Table 6) - .bootrom_size = 0x20000, // "System memory" byte size in hex (Table 6) + .flash_size_reg = 0x1FF1E880, // "Flash size register" (p.3286) + .flash_pagesize = 0x20000, // 128k sector (p.152) + .sram_size = 0x20000, // 128k "DTCM" (Figure 1) + .bootrom_base = + 0x1FF00000, // "System memory" starting address (Table 6) + .bootrom_size = 0x20000, // "System memory" byte size in hex (Table 6) .option_base = STM32_H7_OPTION_BYTES_BASE, .option_size = 44, .flags = CHIP_F_HAS_SWO_TRACING, @@ -712,13 +757,13 @@ static const struct stlink_chipid_params devices[] = { }; const struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chipid) { - const struct stlink_chipid_params *params = NULL; + const struct stlink_chipid_params *params = NULL; - for (size_t n = 0; n < STLINK_ARRAY_SIZE(devices); n++) - if (devices[n].chip_id == chipid) { - params = &devices[n]; - break; - } + for (size_t n = 0; n < STLINK_ARRAY_SIZE(devices); n++) + if (devices[n].chip_id == chipid) { + params = &devices[n]; + break; + } - return(params); + return (params); } diff --git a/src/stlink-lib/flash_loader.c b/src/stlink-lib/flash_loader.c index b55953406..ba5efdb8e 100644 --- a/src/stlink-lib/flash_loader.c +++ b/src/stlink-lib/flash_loader.c @@ -3,98 +3,85 @@ #include #include +#include #include "flash_loader.h" #define FLASH_REGS_BANK2_OFS 0x40 #define FLASH_BANK2_START_ADDR 0x08080000 +#define STM32F0_WDG_KR 0x40003000 +#define STM32H7_WDG_KR 0x58004800 + +#define STM32F0_WDG_KR_KEY_RELOAD 0xAAAA + /* DO NOT MODIFY SOURCECODE DIRECTLY, EDIT ASSEMBLY FILES INSTEAD */ /* flashloaders/stm32f0.s -- compiled with thumb2 */ static const uint8_t loader_code_stm32vl[] = { - 0x16, 0x4f, 0x3c, 0x68, - 0x16, 0x4f, 0x3e, 0x68, - 0x36, 0x19, 0x16, 0x4f, - 0x3d, 0x68, 0x2d, 0x19, - 0x4f, 0xf0, 0x01, 0x07, - 0x33, 0x68, 0x3b, 0x43, - 0x33, 0x60, 0x03, 0x88, - 0x0b, 0x80, 0x4f, 0xf0, - 0x02, 0x07, 0xc0, 0x19, - 0xc9, 0x19, 0x4f, 0xf0, - 0x01, 0x07, 0x2b, 0x68, - 0x3b, 0x42, 0xfa, 0xd0, - 0x4f, 0xf0, 0x04, 0x07, - 0x3b, 0x42, 0x04, 0xd1, + 0x00, 0xbf, 0x00, 0xbf, + 0x0e, 0x4f, 0x1f, 0x44, + 0x0e, 0x4e, 0x3e, 0x44, + 0x0e, 0x4d, 0x3d, 0x44, + 0x4f, 0xf0, 0x01, 0x04, + 0x34, 0x60, 0x04, 0x88, + 0x0c, 0x80, 0x02, 0x30, + 0x02, 0x31, 0x4f, 0xf0, + 0x01, 0x07, 0x2c, 0x68, + 0x3c, 0x42, 0xfc, 0xd1, + 0x4f, 0xf0, 0x14, 0x07, + 0x3c, 0x42, 0x01, 0xd1, + 0x02, 0x3a, 0xf0, 0xdc, 0x4f, 0xf0, 0x01, 0x07, - 0xd2, 0x1b, 0x00, 0x2a, - 0xe6, 0xd1, 0x4f, 0xf0, - 0x01, 0x07, 0x33, 0x68, - 0xbb, 0x43, 0x33, 0x60, - 0x00, 0xbe, 0x00, 0xbf, + 0x34, 0x68, 0xbc, 0x43, + 0x34, 0x60, 0x00, 0xbe, 0x00, 0x20, 0x02, 0x40, 0x10, 0x00, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x00, 0x20, - 0x54, 0x00, 0x00, 0x20, - 0x58, 0x00, 0x00, 0x20 + 0x0c, 0x00, 0x00, 0x00 }; /* flashloaders/stm32f0.s -- thumb1 only, same sequence as for STM32VL, bank ignored */ static const uint8_t loader_code_stm32f0[] = { 0xc0, 0x46, 0xc0, 0x46, - 0x13, 0x4f, 0x3c, 0x68, - 0x13, 0x4f, 0x3e, 0x68, - 0x36, 0x19, 0x13, 0x4f, - 0x3d, 0x68, 0x2d, 0x19, - 0x12, 0x4f, 0x33, 0x68, - 0x3b, 0x43, 0x33, 0x60, - 0x03, 0x88, 0x0b, 0x80, - 0x10, 0x4f, 0xc0, 0x19, - 0xc9, 0x19, 0x0e, 0x4f, - 0x2b, 0x68, 0x3b, 0x42, - 0xfb, 0xd0, 0x0e, 0x4f, - 0x3b, 0x42, 0x03, 0xd1, - 0x0a, 0x4f, 0xd2, 0x1b, - 0x00, 0x2a, 0xeb, 0xd1, - 0x08, 0x4f, 0x33, 0x68, - 0xbb, 0x43, 0x33, 0x60, - 0x00, 0xbe, 0xc0, 0x46, + 0x0c, 0x4f, 0x1f, 0x44, + 0x0c, 0x4e, 0x3e, 0x44, + 0x0c, 0x4d, 0x3d, 0x44, + 0x0c, 0x4c, 0x34, 0x60, + 0x04, 0x88, 0x0c, 0x80, + 0x02, 0x30, 0x02, 0x31, + 0x09, 0x4f, 0x2c, 0x68, + 0x3c, 0x42, 0xfc, 0xd1, + 0x08, 0x4f, 0x3c, 0x42, + 0x01, 0xd1, 0x02, 0x3a, + 0xf2, 0xdc, 0x05, 0x4f, + 0x34, 0x68, 0xbc, 0x43, + 0x34, 0x60, 0x00, 0xbe, 0x00, 0x20, 0x02, 0x40, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x20, - 0x4c, 0x00, 0x00, 0x20, - 0x50, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00 + 0x14, 0x00, 0x00, 0x00 }; -static const uint8_t loader_code_stm32l[] = { +static const uint8_t loader_code_stm32lx[] = { // flashloaders/stm32lx.s - - 0x03, 0x68, 0x0b, 0x60, - 0x4f, 0xf0, 0x04, 0x07, - 0x38, 0x44, 0x39, 0x44, - 0x4f, 0xf0, 0x01, 0x07, - 0xd2, 0x1b, 0x00, 0x2a, - 0xf4, 0xd1, 0x00, 0xbe, + 0x04, 0x68, 0x0c, 0x60, + 0x00, 0xf1, 0x04, 0x00, + 0x01, 0xf1, 0x04, 0x01, + 0x04, 0x3a, 0xf7, 0xdc, + 0x00, 0xbe, 0x00, 0x00 }; static const uint8_t loader_code_stm32f4[] = { // flashloaders/stm32f4.s - - 0xdf, 0xf8, 0x28, 0xc0, - 0xdf, 0xf8, 0x28, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x0b, 0x60, 0x00, 0xf1, + 0xdf, 0xf8, 0x24, 0xc0, + 0xdf, 0xf8, 0x24, 0xa0, + 0xe2, 0x44, 0x04, 0x68, + 0x0c, 0x60, 0x00, 0xf1, 0x04, 0x00, 0x01, 0xf1, 0x04, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xf0, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x04, 0x3a, 0xf2, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -102,17 +89,15 @@ static const uint8_t loader_code_stm32f4[] = { static const uint8_t loader_code_stm32f4_lv[] = { // flashloaders/stm32f4lv.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x4f, 0xea, - 0x82, 0x02, 0x03, 0x78, - 0x0b, 0x70, 0x00, 0xf1, + 0xdf, 0xf8, 0x24, 0xc0, + 0xdf, 0xf8, 0x24, 0xa0, + 0xe2, 0x44, 0x04, 0x78, + 0x0c, 0x70, 0x00, 0xf1, 0x01, 0x00, 0x01, 0xf1, 0x01, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xf0, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x01, 0x3a, 0xf2, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -120,35 +105,33 @@ static const uint8_t loader_code_stm32f4_lv[] = { static const uint8_t loader_code_stm32l4[] = { // flashloaders/stm32l4.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x44, 0x68, 0x0b, 0x60, + 0xdf, 0xf8, 0x28, 0xc0, + 0xdf, 0xf8, 0x28, 0xa0, + 0xe2, 0x44, 0x05, 0x68, + 0x44, 0x68, 0x0d, 0x60, 0x4c, 0x60, 0x00, 0xf1, 0x08, 0x00, 0x01, 0xf1, - 0x08, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, + 0x08, 0x01, 0xda, 0xf8, + 0x00, 0x40, 0x14, 0xf4, + 0x80, 0x3f, 0xfa, 0xd1, + 0x08, 0x3a, 0xf0, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x20, 0x02, 0x40, - 0x12, 0x00, 0x00, 0x00 + 0x10, 0x00, 0x00, 0x00 }; static const uint8_t loader_code_stm32f7[] = { // flashloaders/stm32f7.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x0b, 0x60, 0x00, 0xf1, + 0xdf, 0xf8, 0x28, 0xc0, + 0xdf, 0xf8, 0x28, 0xa0, + 0xe2, 0x44, 0x04, 0x68, + 0x0c, 0x60, 0x00, 0xf1, 0x04, 0x00, 0x01, 0xf1, 0x04, 0x01, 0xbf, 0xf3, 0x4f, 0x8f, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x04, 0x3a, 0xf0, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -156,18 +139,16 @@ static const uint8_t loader_code_stm32f7[] = { static const uint8_t loader_code_stm32f7_lv[] = { // flashloaders/stm32f7lv.s - 0xdf, 0xf8, 0x30, 0xc0, - 0xdf, 0xf8, 0x30, 0xa0, - 0xe2, 0x44, 0x4f, 0xea, - 0x82, 0x02, 0x03, 0x78, - 0x0b, 0x70, 0x00, 0xf1, + 0xdf, 0xf8, 0x28, 0xc0, + 0xdf, 0xf8, 0x28, 0xa0, + 0xe2, 0x44, 0x04, 0x78, + 0x0c, 0x70, 0x00, 0xf1, 0x01, 0x00, 0x01, 0xf1, 0x01, 0x01, 0xbf, 0xf3, 0x4f, 0x8f, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x01, 0x3a, 0xf0, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -176,6 +157,7 @@ static const uint8_t loader_code_stm32f7_lv[] = { int stlink_flash_loader_init(stlink_t *sl, flash_loader_t *fl) { size_t size = 0; + uint32_t dfsr, cfsr, hfsr; // allocate the loader in SRAM if (stlink_flash_loader_write_to_sram(sl, &fl->loader_addr, &size) == -1) { @@ -187,6 +169,27 @@ int stlink_flash_loader_init(stlink_t *sl, flash_loader_t *fl) { fl->buf_addr = fl->loader_addr + (uint32_t)size; ILOG("Successfully loaded flash loader in sram\n"); + // set address of IWDG key register for reset it + if (sl->flash_type == STLINK_FLASH_TYPE_H7) { + fl->iwdg_kr = STM32H7_WDG_KR; + } else { + fl->iwdg_kr = STM32F0_WDG_KR; + } + + /* Clear Fault Status Register for handling flash loader error */ + if (!stlink_read_debug32(sl, STLINK_REG_DFSR, &dfsr) && dfsr) { + ILOG("Clear DFSR\n"); + stlink_write_debug32(sl, STLINK_REG_DFSR, dfsr); + } + if (!stlink_read_debug32(sl, STLINK_REG_CFSR, &cfsr) && cfsr) { + ILOG("Clear CFSR\n"); + stlink_write_debug32(sl, STLINK_REG_CFSR, cfsr); + } + if (!stlink_read_debug32(sl, STLINK_REG_HFSR, &hfsr) && hfsr) { + ILOG("Clear HFSR\n"); + stlink_write_debug32(sl, STLINK_REG_HFSR, hfsr); + } + return(0); } @@ -233,8 +236,8 @@ int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* sl->chip_id == STLINK_CHIPID_STM32_L0 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2) { // STM32l - loader_code = loader_code_stm32l; - loader_size = sizeof(loader_code_stm32l); + loader_code = loader_code_stm32lx; + loader_size = sizeof(loader_code_stm32lx); } else if (sl->core_id == STM32VL_CORE_ID || sl->chip_id == STLINK_CHIPID_STM32_F1_MEDIUM || sl->chip_id == STLINK_CHIPID_STM32_F1_HIGH || @@ -313,11 +316,9 @@ int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size) { struct stlink_reg rr; - int i = 0; - size_t count = 0; + unsigned timeout; uint32_t flash_base = 0; - const char *error = NULL; - uint32_t dhcsr, dfsr; + uint32_t dhcsr, dfsr, cfsr, hfsr; DLOG("Running flash loader, write address:%#x, size: %u\n", target, (unsigned int)size); @@ -328,22 +329,6 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe return(-1); } - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { - count = size / sizeof(uint16_t); - - if (size % sizeof(uint16_t)) { ++count; } - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4 || - sl->flash_type == STLINK_FLASH_TYPE_L0) { - count = size / sizeof(uint32_t); - - if (size % sizeof(uint32_t)) { ++count; } - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - count = size / sizeof(uint64_t); - - if (size % sizeof(uint64_t)) { ++count; } - } - if ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (target >= FLASH_BANK2_START_ADDR)) { flash_base = FLASH_REGS_BANK2_OFS; } @@ -351,13 +336,18 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe /* Setup core */ stlink_write_reg(sl, fl->buf_addr, 0); // source stlink_write_reg(sl, target, 1); // target - stlink_write_reg(sl, (uint32_t)count, 2); // count + stlink_write_reg(sl, (uint32_t)size, 2); // count stlink_write_reg(sl, flash_base, 3); // flash register base // only used on VL/F1_XL, but harmless for others stlink_write_reg(sl, fl->loader_addr, 15); // pc register + /* Reset IWDG */ + if (fl->iwdg_kr) { + stlink_write_debug32(sl, fl->iwdg_kr, STM32F0_WDG_KR_KEY_RELOAD); + } + /* Run loader */ - stlink_run(sl); + stlink_run(sl, RUN_FLASH_LOADER); /* This piece of code used to try to spin for .1 second by waiting doing 10000 rounds of 10 µs. * But because this usually runs on Unix-like OSes, the 10 µs get rounded up to the "tick" @@ -368,36 +358,52 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe * the OS uses, the wait until the error message is reduced to the same order of magnitude * as what was intended. -- REW. */ -#define WAIT_ROUNDS 40 // wait until done (reaches breakpoint) - for (i = 0; i < WAIT_ROUNDS; i++) { + timeout = time_ms() + 500; + while (time_ms() < timeout) { usleep(10000); - if (stlink_is_core_halted(sl)) { break; } + if (stlink_is_core_halted(sl)) { + timeout = 0; + break; + } } - if (i >= WAIT_ROUNDS) { - error = "Flash loader run error"; + if (timeout) { + ELOG("Flash loader run error\n"); goto error; } // check written byte count stlink_read_reg(sl, 2, &rr); - if (rr.r[2] != 0) { - error = "Write error"; + /* The chunk size for loading is not rounded. The flash loader + * subtracts the size of the written block (1-8 bytes) from + * the remaining size each time. A negative value may mean that + * several bytes garbage has been written due to the unaligned + * firmware size. + */ + if ((int32_t)rr.r[2] > 0 || (int32_t)rr.r[2] < -7) { + ELOG("Write error\n"); goto error; } return(0); error: - dhcsr = dfsr = 0; + dhcsr = dfsr = cfsr = hfsr = 0; stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); stlink_read_debug32(sl, STLINK_REG_DFSR, &dfsr); + stlink_read_debug32(sl, STLINK_REG_CFSR, &cfsr); + stlink_read_debug32(sl, STLINK_REG_HFSR, &hfsr); stlink_read_all_regs(sl, &rr); - ELOG("%s (R2 0x%08X R15 0x%08X DHCSR 0x%08X DFSR 0x%08X)\n", error, rr.r[2], rr.r[15], dhcsr, dfsr); + + WLOG("Loader state: R2 0x%X R15 0x%X\n", rr.r[2], rr.r[15]); + if (dhcsr != 0x3000B || dfsr || cfsr || hfsr) { + WLOG("MCU state: DHCSR 0x%X DFSR 0x%X CFSR 0x%X HFSR 0x%X\n", + dhcsr, dfsr, cfsr, hfsr); + } return(-1); } diff --git a/src/stlink-lib/helper.c b/src/stlink-lib/helper.c index 32d9b6c8d..1f0f71b8d 100644 --- a/src/stlink-lib/helper.c +++ b/src/stlink-lib/helper.c @@ -1,6 +1,7 @@ #include #include +#include #ifdef STLINK_HAVE_SYS_TIME_H #include @@ -13,3 +14,16 @@ unsigned time_ms() { gettimeofday(&tv, NULL); return (unsigned)(tv.tv_sec * 1000 + tv.tv_usec / 1000); } + +int arg_parse_freq(const char *str) { + char *tail; + int value = (int)strtol(str, &tail, 10); + + if ((tail[0] == 'm' || tail[0] == 'M') && tail[1] == '\0') { + value = value*1000; + } else if (((tail[0] != 'k' && tail[0] != 'K') || tail[1] != '\0') && tail[0] != '\0') { + return -1; + } + + return value; +} diff --git a/src/stlink-lib/helper.h b/src/stlink-lib/helper.h index 12c2ea2a7..96467377a 100644 --- a/src/stlink-lib/helper.h +++ b/src/stlink-lib/helper.h @@ -3,4 +3,6 @@ unsigned time_ms(); +int arg_parse_freq(const char *str); + #endif /* SYS_HELPER_H */ diff --git a/src/stlink-lib/logging.c b/src/stlink-lib/logging.c index ce0a2baab..87978230d 100644 --- a/src/stlink-lib/logging.c +++ b/src/stlink-lib/logging.c @@ -1,12 +1,13 @@ /* * UglyLogging * - * Slow, yet another wheel reinvented, but enough to make the rest of our code pretty enough. + * Slow, yet another wheel reinvented, but enough to make the rest of our code + * pretty enough. */ +#include #include #include #include -#include #include #include "logging.h" @@ -14,77 +15,89 @@ static int max_level = UDEBUG; int ugly_init(int maximum_threshold) { - max_level = maximum_threshold; - return(0); + max_level = maximum_threshold; + return (0); } int ugly_log(int level, const char *tag, const char *format, ...) { - if (level > max_level) { - return(0); - } + if (level > max_level) { + return (0); + } - fflush(stdout); // flush to maintain order of streams + fflush(stdout); // flush to maintain order of streams - va_list args; - va_start(args, format); - time_t mytt = time(NULL); - struct tm *tt; - tt = localtime(&mytt); - fprintf(stderr, "%d-%02d-%02dT%02d:%02d:%02d ", tt->tm_year + 1900, tt->tm_mon + 1, - tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec); + va_list args; + va_start(args, format); + time_t mytt = time(NULL); + struct tm *tt; + tt = localtime(&mytt); + fprintf(stderr, "%d-%02d-%02dT%02d:%02d:%02d ", tt->tm_year + 1900, + tt->tm_mon + 1, tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec); - switch (level) { - case UDEBUG: - fprintf(stderr, "DEBUG %s: ", tag); - break; - case UINFO: - fprintf(stderr, "INFO %s: ", tag); - break; - case UWARN: - fprintf(stderr, "WARN %s: ", tag); - break; - case UERROR: - fprintf(stderr, "ERROR %s: ", tag); - break; - default: - fprintf(stderr, "%d %s: ", level, tag); - break; - } + switch (level) { + case UDEBUG: + fprintf(stderr, "DEBUG %s: ", tag); + break; + case UINFO: + fprintf(stderr, "INFO %s: ", tag); + break; + case UWARN: + fprintf(stderr, "WARN %s: ", tag); + break; + case UERROR: + fprintf(stderr, "ERROR %s: ", tag); + break; + default: + fprintf(stderr, "%d %s: ", level, tag); + break; + } - vfprintf(stderr, format, args); - fflush(stderr); - va_end(args); - return(1); + vfprintf(stderr, format, args); + fflush(stderr); + va_end(args); + return (1); } /* * Log message levels. - * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) + * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library + * (default) * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr - * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr + * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to + * stderr + * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to + * stderr + * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are + * printed to stderr */ int ugly_libusb_log_level(enum ugly_loglevel v) { #ifdef __FreeBSD__ - // FreeBSD includes its own reimplementation of libusb. - // Its libusb_set_debug() function expects a lib_debug_level - // instead of a lib_log_level and is verbose enough to drown out - // all other output. - switch (v) { - case UDEBUG: return (3); // LIBUSB_DEBUG_FUNCTION + LIBUSB_DEBUG_TRANSFER - case UINFO: return (1); // LIBUSB_DEBUG_FUNCTION only - case UWARN: return (0); // LIBUSB_DEBUG_NO - case UERROR: return (0); // LIBUSB_DEBUG_NO - } - return (0); + // FreeBSD includes its own reimplementation of libusb. + // Its libusb_set_debug() function expects a lib_debug_level + // instead of a lib_log_level and is verbose enough to drown out + // all other output. + switch (v) { + case UDEBUG: + return (3); // LIBUSB_DEBUG_FUNCTION + LIBUSB_DEBUG_TRANSFER + case UINFO: + return (1); // LIBUSB_DEBUG_FUNCTION only + case UWARN: + return (0); // LIBUSB_DEBUG_NO + case UERROR: + return (0); // LIBUSB_DEBUG_NO + } + return (0); #else - switch (v) { - case UDEBUG: return (4); - case UINFO: return (3); - case UWARN: return (2); - case UERROR: return (1); - } + switch (v) { + case UDEBUG: + return (4); + case UINFO: + return (3); + case UWARN: return (2); + case UERROR: + return (1); + } + return (2); #endif } diff --git a/src/stlink-lib/reg.h b/src/stlink-lib/reg.h index 6d2c9f1af..b581a269c 100644 --- a/src/stlink-lib/reg.h +++ b/src/stlink-lib/reg.h @@ -3,6 +3,15 @@ #define STLINK_REG_CM3_CPUID 0xE000ED00 +#define STLINK_REG_CMx_CPUID_PARTNO_CM0 0xC20 +#define STLINK_REG_CMx_CPUID_PARTNO_CM0P 0xC60 +#define STLINK_REG_CMx_CPUID_PARTNO_CM3 0xC23 +#define STLINK_REG_CMx_CPUID_PARTNO_CM4 0xC24 +#define STLINK_REG_CMx_CPUID_PARTNO_CM7 0xC27 +#define STLINK_REG_CMx_CPUID_PARTNO_CM33 0xD21 +#define STLINK_REG_CMx_CPUID_IMPL_ARM 0x41 + + #define STLINK_REG_CM3_FP_CTRL 0xE0002000 // Flash Patch Control Register #define STLINK_REG_CM3_FP_COMPn(n) (0xE0002008 + n*4) #define STLINK_REG_CM3_FP_CTRL_KEY (1 << 1) @@ -19,6 +28,12 @@ #define STLINK_REG_CM3_DWT_FUNn(n) (0xE0001028 + n*16) /* Cortex™-M3 Technical Reference Manual */ +/* Configurable Fault Status Register */ +#define STLINK_REG_CFSR 0xE000ED28 + +/* Hard Fault Status Register */ +#define STLINK_REG_HFSR 0xE000ED2C + /* Debug Halting Control and Status Register */ #define STLINK_REG_DFSR 0xE000ED30 #define STLINK_REG_DFSR_HALT (1 << 0) diff --git a/src/stlink-lib/sg.c b/src/stlink-lib/sg.c index 840466e75..07971284f 100644 --- a/src/stlink-lib/sg.c +++ b/src/stlink-lib/sg.c @@ -731,8 +731,9 @@ void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) { } // force the core exit the debug mode. -int _stlink_sg_run(stlink_t *sl) { +int _stlink_sg_run(stlink_t *sl, enum run_type type) { struct stlink_libsg *sg = sl->backend_data; + (void)(type); //unused clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE; sl->q_len = 2; @@ -1114,7 +1115,7 @@ stlink_t* stlink_v1_open(const int verbose, int reset) { stlink_enter_swd_mode(sl); // now we are ready to read the parameters - if (reset) { stlink_reset(sl); } + if (reset) { stlink_reset(sl, RESET_AUTO); } stlink_load_device_params(sl); ILOG("Successfully opened a stlink v1 debugger\n"); diff --git a/src/stlink-lib/usb.c b/src/stlink-lib/usb.c index 0168834ca..2754db06f 100644 --- a/src/stlink-lib/usb.c +++ b/src/stlink-lib/usb.c @@ -46,7 +46,7 @@ static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, u // get abs value for comparison current_diff = (current_diff > 0) ? current_diff : -current_diff; - if ((current_diff < speed_diff) && khz >= map[i]) { + if (current_diff < speed_diff) { speed_diff = current_diff; speed_index = i; } @@ -301,7 +301,7 @@ int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { if (ret == -1) { return(ret); } - ret = send_only(slu, 0, data, len); + ret = send_only(slu, 1, data, len); if (ret == -1) { return(ret); } @@ -431,6 +431,8 @@ int _stlink_usb_status(stlink_t * sl) { } else { sl->core_stat = TARGET_UNKNOWN; } + } else { + sl->core_stat = TARGET_UNKNOWN; } return(0); @@ -469,19 +471,14 @@ int _stlink_usb_enter_swd_mode(stlink_t * sl) { unsigned char* const cmd = sl->c_buf; ssize_t size; unsigned char* const data = sl->q_buf; - const uint32_t rep_len = sl->version.stlink_v > 1 ? 2 : 0; + const uint32_t rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 2; int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; // select correct API-Version for entering SWD mode: V1 API (0x20) or V2 API (0x30). cmd[i++] = sl->version.jtag_api == STLINK_JTAG_API_V1 ? STLINK_DEBUG_APIV1_ENTER : STLINK_DEBUG_APIV2_ENTER; cmd[i++] = STLINK_DEBUG_ENTER_SWD; - - if (rep_len == 0) { - size = send_only(slu, 1, cmd, slu->cmd_len); - } else { - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - } + size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { printf("[!] send_recv STLINK_DEBUG_ENTER\n"); @@ -515,13 +512,8 @@ int _stlink_usb_reset(stlink_t * sl) { unsigned char* const data = sl->q_buf; unsigned char* const cmd = sl->c_buf; ssize_t size; - uint32_t dhcsr; - unsigned timeout; int i, rep_len = 2; - // clear S_RESET_ST in DHCSR registr - _stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); - // send reset command i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; @@ -539,30 +531,7 @@ int _stlink_usb_reset(stlink_t * sl) { return((int)size); } - usleep(10000); - - dhcsr = 0; - _stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); - if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) { - // reset not done yet - // try reset through AIRCR so that NRST does not need to be connected - - WLOG("NRST is not connected\n"); - DLOG("Using reset through SYSRESETREQ\n"); - return stlink_soft_reset(sl, 0); - } - - // waiting for a reset within 500ms - timeout = time_ms() + 500; - while (time_ms() < timeout) { - // DDI0337E, p. 10-4, Debug Halting Control and Status Register - dhcsr = STLINK_REG_DHCSR_S_RESET_ST; - _stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); - if ((dhcsr&STLINK_REG_DHCSR_S_RESET_ST) == 0) - return(0); - } - - return(-1); + return(0); } int _stlink_usb_jtag_reset(stlink_t * sl, int value) { @@ -621,14 +590,17 @@ int _stlink_usb_step(stlink_t* sl) { /** * This seems to do a good job of restarting things from the beginning? * @param sl + * @param type */ -int _stlink_usb_run(stlink_t* sl) { +int _stlink_usb_run(stlink_t* sl, enum run_type type) { struct stlink_libusb * const slu = sl->backend_data; int res; if (sl->version.jtag_api != STLINK_JTAG_API_V1) { - res = _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN); + res = _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, + STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN | + ((type==RUN_FLASH_LOADER)?STLINK_REG_DHCSR_C_MASKINTS:0)); return(res); } @@ -744,6 +716,8 @@ int _stlink_usb_set_swdclk(stlink_t* sl, int clk_freq) { } return(0); + } else if (clk_freq) { + WLOG("ST-Link firmware does not support frequency setup\n"); } return(-1); @@ -1162,7 +1136,44 @@ static stlink_backend_t _stlink_usb_backend = { _stlink_usb_read_trace }; -stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq) { +/* return the length of serial or (0) in case of errors */ +size_t stlink_serial(struct libusb_device_handle *handle, struct libusb_device_descriptor *desc, char *serial) { + unsigned char desc_serial[(STLINK_SERIAL_LENGTH) * 2]; + + /* truncate the string in the serial buffer */ + serial[0] = '\0'; + + /* get the LANGID from String Descriptor Zero */ + int ret = libusb_get_string_descriptor(handle, 0, 0, desc_serial, sizeof(desc_serial)); + if (ret < 4) return 0; + + uint32_t langid = desc_serial[2] | (desc_serial[3] << 8); + + /* get the serial */ + ret = libusb_get_string_descriptor(handle, desc->iSerialNumber, langid, desc_serial, + sizeof(desc_serial)); + if (ret < 0) return 0; // could not read serial + + unsigned char len = desc_serial[0]; + + if (len == ((STLINK_SERIAL_LENGTH + 1) * 2)) { /* len == 50 */ + /* good ST-Link adapter */ + ret = libusb_get_string_descriptor_ascii( + handle, desc->iSerialNumber, (unsigned char *)serial, STLINK_SERIAL_BUFFER_SIZE); + if (ret < 0) return 0; + } else if (len == ((STLINK_SERIAL_LENGTH / 2 + 1) * 2)) { /* len == 26 */ + /* fix-up the buggy serial */ + for (unsigned int i = 0; i < STLINK_SERIAL_LENGTH; i += 2) + sprintf(serial + i, "%02X", desc_serial[i + 2]); + serial[STLINK_SERIAL_LENGTH] = '\0'; + } else { + return 0; + } + + return strlen(serial); +} + +stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect, char serial[STLINK_SERIAL_BUFFER_SIZE], int freq) { stlink_t* sl = NULL; struct stlink_libusb* slu = NULL; int ret = -1; @@ -1239,15 +1250,14 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL if (ret) { continue; } // could not open device - sl->serial_size = libusb_get_string_descriptor_ascii( - handle, desc.iSerialNumber, (unsigned char *)sl->serial, sizeof(sl->serial)); + size_t serial_len = stlink_serial(handle, &desc, sl->serial); libusb_close(handle); - if (sl->serial_size < 0) { continue; } // could not read serial + if (serial_len != STLINK_SERIAL_LENGTH) { continue; } // could not read the serial // if no serial provided, or if serial match device, fixup version and protocol - if (((serial == NULL) || (*serial == 0)) || (memcmp(serial, &sl->serial, sl->serial_size) == 0)) { + if (((serial == NULL) || (*serial == 0)) || (memcmp(serial, &sl->serial, STLINK_SERIAL_LENGTH) == 0)) { if (STLINK_V1_USB_PID(desc.idProduct)) { slu->protocoll = 1; sl->version.stlink_v = 1; @@ -1347,27 +1357,7 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL DLOG("JTAG/SWD freq set to %d\n", freq); stlink_set_swdclk(sl, freq); - if (reset == 2) { - stlink_jtag_reset(sl, 0); - - if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } - - stlink_force_debug(sl); - stlink_jtag_reset(sl, 1); - usleep(10000); - } - - - if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } - - if (reset == 1) { - if ( sl->version.stlink_v > 1) { stlink_jtag_reset(sl, 2); } - - stlink_reset(sl); - usleep(10000); - } - - stlink_load_device_params(sl); + stlink_target_connect(sl, connect); return(sl); on_libusb_error: @@ -1387,7 +1377,7 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL return(NULL); } -static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { +static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[], enum connect_type connect, int freq) { stlink_t **_sldevs; libusb_device *dev; int i = 0; @@ -1436,7 +1426,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { if (!STLINK_SUPPORTED_USB_PID(desc.idProduct)) { continue; } struct libusb_device_handle* handle; - char serial[STLINK_SERIAL_MAX_SIZE] = {0, }; + char serial[STLINK_SERIAL_BUFFER_SIZE] = {0, }; ret = libusb_open(dev, &handle); @@ -1450,13 +1440,13 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { break; } - ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)&serial, sizeof(serial)); + size_t serial_len = stlink_serial(handle, &desc, serial); libusb_close(handle); - if (ret < 0) { continue; } + if (serial_len != STLINK_SERIAL_LENGTH) { continue; } - stlink_t *sl = stlink_open_usb(0, 1, serial, 0); + stlink_t *sl = stlink_open_usb(0, connect, serial, freq); if (!sl) { ELOG("Failed to open USB device %#06x:%#06x\n", desc.idVendor, desc.idProduct); @@ -1471,7 +1461,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { return(slcur); } -size_t stlink_probe_usb(stlink_t **stdevs[]) { +size_t stlink_probe_usb(stlink_t **stdevs[], enum connect_type connect, int freq) { libusb_device **devs; stlink_t **sldevs; @@ -1487,7 +1477,7 @@ size_t stlink_probe_usb(stlink_t **stdevs[]) { if (cnt < 0) { return(0); } - slcnt = stlink_probe_usb_devs(devs, &sldevs); + slcnt = stlink_probe_usb_devs(devs, &sldevs, connect, freq); libusb_free_device_list(devs, 1); libusb_exit(NULL); diff --git a/src/stlink-lib/usb.h b/src/stlink-lib/usb.h index 717a82f6d..27de32700 100644 --- a/src/stlink-lib/usb.h +++ b/src/stlink-lib/usb.h @@ -62,13 +62,13 @@ struct stlink_libusb { /** * Open a stlink * @param verbose Verbosity loglevel - * @param reset Reset stlink programmer + * @param connect Type of connect to target * @param serial Serial number to search for, when NULL the first stlink found is opened (binary format) * @retval NULL Error while opening the stlink * @retval !NULL Stlink found and ready to use */ -stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq); -size_t stlink_probe_usb(stlink_t **stdevs[]); +stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect, char serial[STLINK_SERIAL_BUFFER_SIZE], int freq); +size_t stlink_probe_usb(stlink_t **stdevs[], enum connect_type connect, int freq); void stlink_probe_usb_free(stlink_t **stdevs[], size_t size); #ifdef __cplusplus diff --git a/tests/flash.c b/tests/flash.c index a8d479b2d..132066aba 100644 --- a/tests/flash.c +++ b/tests/flash.c @@ -131,17 +131,6 @@ static struct Test tests[] = { .freq = 5, .format = FLASH_FORMAT_BINARY } }, - { "--debug --freq=6k --reset write test.bin 0x80000000", -1, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 6, - .format = FLASH_FORMAT_BINARY } - }, { "--debug --reset read test.bin 0x80000000 1000", 0, { .cmd = FLASH_CMD_READ, .serial = { 0 }, @@ -211,10 +200,10 @@ static struct Test tests[] = { { "--debug --reset --format=binary write test.hex", -1, FLASH_OPTS_INITIALIZER }, { "--debug --reset --format=ihex write test.hex 0x80000000", -1, FLASH_OPTS_INITIALIZER }, { "--debug --reset write test.hex sometext", -1, FLASH_OPTS_INITIALIZER }, - { "--serial A1020304 erase sometext", -1, FLASH_OPTS_INITIALIZER }, - { "--serial A1020304 erase", 0, + { "--serial ABCEFF544851717867216044 erase sometext", -1, FLASH_OPTS_INITIALIZER }, + { "--serial ABCEFF544851717867216044 erase", 0, { .cmd = FLASH_CMD_ERASE, - .serial = "\xA1\x02\x03\x04", + .serial = "ABCEFF544851717867216044", .filename = NULL, .addr = 0, .size = 0, @@ -223,9 +212,9 @@ static struct Test tests[] = { .freq = 0, .format = FLASH_FORMAT_BINARY } }, - { "--serial=A1020304 erase", 0, + { "--serial=ABCEFF544851717867216044 erase", 0, { .cmd = FLASH_CMD_ERASE, - .serial = "\xA1\x02\x03\x04", + .serial = "ABCEFF544851717867216044", .filename = NULL, .addr = 0, .size = 0, diff --git a/tests/sg.c b/tests/sg.c index 745df845f..d88fbe760 100644 --- a/tests/sg.c +++ b/tests/sg.c @@ -46,7 +46,7 @@ int main(void) { // main() ripped out of old stlink-hw.c stlink_core_id(sl); stlink_status(sl); // stlink_force_debug(sl); - stlink_reset(sl); + stlink_reset(sl, RESET_AUTO); stlink_status(sl); // core system control block stlink_read_mem32(sl, 0xe000ed00, 4); @@ -159,7 +159,7 @@ int main(void) { // main() ripped out of old stlink-hw.c #endif #if 0 - stlink_run(sl); + stlink_run(sl, RUN_NORMAL); stlink_status(sl); stlink_force_debug(sl); stlink_status(sl); @@ -196,7 +196,7 @@ int main(void) { // main() ripped out of old stlink-hw.c #endif #if 0 - stlink_run(sl); + stlink_run(sl, RUN_NORMAL); stlink_status(sl); // back to mass mode, just in case ... stlink_exit_debug_mode(sl); diff --git a/tests/usb.c b/tests/usb.c index 03c135f00..742f5c578 100644 --- a/tests/usb.c +++ b/tests/usb.c @@ -93,7 +93,7 @@ int main(int ac, char** av) { stlink_status(sl); printf("-- reset\n"); - stlink_reset(sl); + stlink_reset(sl, RESET_AUTO); stlink_force_debug(sl); /* Test reg write */ stlink_write_reg(sl, 0x01234567, 3); @@ -111,7 +111,7 @@ int main(int ac, char** av) { stlink_step(sl); printf("-- run\n"); - stlink_run(sl); + stlink_run(sl, RUN_NORMAL); printf("-- exit_debug_mode\n"); stlink_exit_debug_mode(sl);