├── .github └── workflows │ └── action.yml ├── Kconfig ├── README.md ├── RTT ├── SEGGER_RTT.c ├── SEGGER_RTT.h ├── SEGGER_RTT_ASM_ARMv7M.S ├── SEGGER_RTT_Conf.h └── SEGGER_RTT_printf.c ├── SConscript ├── adapter ├── drv_rtt.c └── drv_swo.c └── images ├── image-20210523144320179.png ├── image-20210523144722163.png ├── image-20210523145133760.png ├── image-20210523145308304.png ├── image-20210523145349136.png ├── image-20210525025001074.png ├── image-20210525030747681.png ├── image-20210529222436909.png ├── image-20210529222511146.png ├── image-20210529222625567.png ├── image-20210529222732304.png ├── image-20210529222806327.png ├── image-20210529222831650.png └── image-20221007203535784.png /.github/workflows/action.yml: -------------------------------------------------------------------------------- 1 | name: SEGGER_RTT 2 | 3 | # Controls when the action will run. Triggers the workflow on push or pull request 4 | # events but only for the master branch 5 | on: 6 | # Runs at 16:00 UTC (BeiJing 00:00) on the 1st of every month 7 | schedule: 8 | - cron: '0 1 15 3,9 *' 9 | push: 10 | branches: 11 | - main 12 | paths-ignore: 13 | - documentation/** 14 | - '**/README.md' 15 | - '**/README_zh.md' 16 | pull_request: 17 | branches: 18 | - main 19 | paths-ignore: 20 | - documentation/** 21 | - '**/README.md' 22 | - '**/README_zh.md' 23 | 24 | jobs: 25 | build: 26 | runs-on: ubuntu-latest 27 | name: ${{ matrix.legs.RTT_BSP }} 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | legs: 32 | - {RTT_BSP: "acm32/acm32f0x0-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 33 | - {RTT_BSP: "CME_M7", RTT_TOOL_CHAIN: "sourcery-arm"} 34 | - {RTT_BSP: "apm32/apm32f103xe-minibroard", RTT_TOOL_CHAIN: "sourcery-arm"} 35 | - {RTT_BSP: "apollo2", RTT_TOOL_CHAIN: "sourcery-arm"} 36 | - {RTT_BSP: "asm9260t", RTT_TOOL_CHAIN: "sourcery-arm"} 37 | - {RTT_BSP: "at91/at91sam9g45", RTT_TOOL_CHAIN: "sourcery-arm"} 38 | - {RTT_BSP: "at91/at91sam9260", RTT_TOOL_CHAIN: "sourcery-arm"} 39 | - {RTT_BSP: "allwinner_tina", RTT_TOOL_CHAIN: "sourcery-arm"} 40 | #- {RTT_BSP: "cypress/psoc6-cy8cproto-4343w", RTT_TOOL_CHAIN: "sourcery-arm"} 41 | - {RTT_BSP: "ft32/ft32f072xb-starter", RTT_TOOL_CHAIN: "sourcery-arm"} 42 | - {RTT_BSP: "gd32/arm/gd32103c-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 43 | - {RTT_BSP: "gd32/arm/gd32105c-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 44 | - {RTT_BSP: "gd32/arm/gd32105r-start", RTT_TOOL_CHAIN: "sourcery-arm"} 45 | - {RTT_BSP: "gd32/arm/gd32107c-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 46 | - {RTT_BSP: "gd32/arm/gd32205r-start", RTT_TOOL_CHAIN: "sourcery-arm"} 47 | - {RTT_BSP: "gd32/arm/gd32207i-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 48 | - {RTT_BSP: "gd32/arm/gd32303e-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 49 | - {RTT_BSP: "gd32/arm/gd32305r-start", RTT_TOOL_CHAIN: "sourcery-arm"} 50 | - {RTT_BSP: "gd32/arm/gd32307e-start", RTT_TOOL_CHAIN: "sourcery-arm"} 51 | - {RTT_BSP: "gd32/arm/gd32407v-start", RTT_TOOL_CHAIN: "sourcery-arm"} 52 | - {RTT_BSP: "gd32/arm/gd32450z-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 53 | - {RTT_BSP: "gd32e230k-start", RTT_TOOL_CHAIN: "sourcery-arm"} 54 | - {RTT_BSP: "gd32vf103v-eval", RTT_TOOL_CHAIN: "sourcery-riscv-none-embed"} 55 | - {RTT_BSP: "gd32303e-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 56 | - {RTT_BSP: "gd32450z-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 57 | - {RTT_BSP: "imx6sx/cortex-a9", RTT_TOOL_CHAIN: "sourcery-arm"} 58 | - {RTT_BSP: "imxrt/imxrt1052-atk-commander", RTT_TOOL_CHAIN: "sourcery-arm"} 59 | - {RTT_BSP: "imxrt/imxrt1052-fire-pro", RTT_TOOL_CHAIN: "sourcery-arm"} 60 | - {RTT_BSP: "imxrt/imxrt1052-nxp-evk", RTT_TOOL_CHAIN: "sourcery-arm"} 61 | - {RTT_BSP: "imxrt/imxrt1052-seeed-ArchMix", RTT_TOOL_CHAIN: "sourcery-arm"} 62 | - {RTT_BSP: "imxrt/imxrt1060-nxp-evk", RTT_TOOL_CHAIN: "sourcery-arm"} 63 | - {RTT_BSP: "imxrt/imxrt1064-nxp-evk", RTT_TOOL_CHAIN: "sourcery-arm"} 64 | - {RTT_BSP: "tm4c123bsp", RTT_TOOL_CHAIN: "sourcery-arm"} 65 | - {RTT_BSP: "tm4c129x", RTT_TOOL_CHAIN: "sourcery-arm"} 66 | - {RTT_BSP: "lpc55sxx/lpc55s69_nxp_evk", RTT_TOOL_CHAIN: "sourcery-arm"} 67 | - {RTT_BSP: "lpc408x", RTT_TOOL_CHAIN: "sourcery-arm"} 68 | - {RTT_BSP: "lpc1114", RTT_TOOL_CHAIN: "sourcery-arm"} 69 | - {RTT_BSP: "lpc54114-lite", RTT_TOOL_CHAIN: "sourcery-arm"} 70 | - {RTT_BSP: "mini2440", RTT_TOOL_CHAIN: "sourcery-arm"} 71 | - {RTT_BSP: "nrf5x/nrf51822", RTT_TOOL_CHAIN: "sourcery-arm"} 72 | - {RTT_BSP: "nrf5x/nrf52832", RTT_TOOL_CHAIN: "sourcery-arm"} 73 | - {RTT_BSP: "nrf5x/nrf52833", RTT_TOOL_CHAIN: "sourcery-arm"} 74 | - {RTT_BSP: "nrf5x/nrf52840", RTT_TOOL_CHAIN: "sourcery-arm"} 75 | - {RTT_BSP: "qemu-vexpress-a9", RTT_TOOL_CHAIN: "sourcery-arm"} 76 | #- {RTT_BSP: "qemu-vexpress-gemini", RTT_TOOL_CHAIN: "sourcery-arm"} 77 | - {RTT_BSP: "stm32/stm32f072-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 78 | - {RTT_BSP: "stm32/stm32f091-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 79 | - {RTT_BSP: "stm32/stm32f103-100ask-mini", RTT_TOOL_CHAIN: "sourcery-arm"} 80 | - {RTT_BSP: "stm32/stm32f103-100ask-pro", RTT_TOOL_CHAIN: "sourcery-arm"} 81 | - {RTT_BSP: "stm32/stm32f103-atk-nano", RTT_TOOL_CHAIN: "sourcery-arm"} 82 | - {RTT_BSP: "stm32/stm32f103-atk-warshipv3", RTT_TOOL_CHAIN: "sourcery-arm"} 83 | - {RTT_BSP: "stm32/stm32f103-blue-pill", RTT_TOOL_CHAIN: "sourcery-arm"} 84 | - {RTT_BSP: "stm32/stm32f103-dofly-lyc8", RTT_TOOL_CHAIN: "sourcery-arm"} 85 | - {RTT_BSP: "stm32/stm32f103-dofly-M3S", RTT_TOOL_CHAIN: "sourcery-arm"} 86 | - {RTT_BSP: "stm32/stm32f103-fire-arbitrary", RTT_TOOL_CHAIN: "sourcery-arm"} 87 | - {RTT_BSP: "stm32/stm32f103-gizwits-gokitv21", RTT_TOOL_CHAIN: "sourcery-arm"} 88 | - {RTT_BSP: "stm32/stm32f103-hw100k-ibox", RTT_TOOL_CHAIN: "sourcery-arm"} 89 | - {RTT_BSP: "stm32/stm32f103-onenet-nbiot", RTT_TOOL_CHAIN: "sourcery-arm"} 90 | - {RTT_BSP: "stm32/stm32f103-yf-ufun", RTT_TOOL_CHAIN: "sourcery-arm"} 91 | - {RTT_BSP: "stm32/stm32f107-uc-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 92 | - {RTT_BSP: "stm32/stm32f207-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 93 | - {RTT_BSP: "stm32/stm32f302-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 94 | - {RTT_BSP: "stm32/stm32f401-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 95 | - {RTT_BSP: "stm32/stm32f405-smdz-breadfruit", RTT_TOOL_CHAIN: "sourcery-arm"} 96 | - {RTT_BSP: "stm32/stm32f407-armfly-v5", RTT_TOOL_CHAIN: "sourcery-arm"} 97 | - {RTT_BSP: "stm32/stm32f407-atk-explorer", RTT_TOOL_CHAIN: "sourcery-arm"} 98 | - {RTT_BSP: "stm32/stm32f407-robomaster-c", RTT_TOOL_CHAIN: "sourcery-arm"} 99 | - {RTT_BSP: "stm32/stm32f407-st-discovery", RTT_TOOL_CHAIN: "sourcery-arm"} 100 | - {RTT_BSP: "stm32/stm32f410-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 101 | - {RTT_BSP: "stm32/stm32f411-atk-nano", RTT_TOOL_CHAIN: "sourcery-arm"} 102 | - {RTT_BSP: "stm32/stm32f411-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 103 | #- {RTT_BSP: "stm32/stm32f411-weact-MiniF4", RTT_TOOL_CHAIN: "sourcery-arm"} 104 | - {RTT_BSP: "stm32/stm32f412-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 105 | - {RTT_BSP: "stm32/stm32f413-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 106 | - {RTT_BSP: "stm32/stm32f427-robomaster-a", RTT_TOOL_CHAIN: "sourcery-arm"} 107 | - {RTT_BSP: "stm32/stm32f429-armfly-v6", RTT_TOOL_CHAIN: "sourcery-arm"} 108 | - {RTT_BSP: "stm32/stm32f429-atk-apollo", RTT_TOOL_CHAIN: "sourcery-arm"} 109 | - {RTT_BSP: "stm32/stm32f429-fire-challenger", RTT_TOOL_CHAIN: "sourcery-arm"} 110 | - {RTT_BSP: "stm32/stm32f429-st-disco", RTT_TOOL_CHAIN: "sourcery-arm"} 111 | - {RTT_BSP: "stm32/stm32f446-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 112 | - {RTT_BSP: "stm32/stm32f469-st-disco", RTT_TOOL_CHAIN: "sourcery-arm"} 113 | - {RTT_BSP: "stm32/stm32f746-st-disco", RTT_TOOL_CHAIN: "sourcery-arm"} 114 | - {RTT_BSP: "stm32/stm32f746-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 115 | - {RTT_BSP: "stm32/stm32f767-atk-apollo", RTT_TOOL_CHAIN: "sourcery-arm"} 116 | - {RTT_BSP: "stm32/stm32f767-fire-challenger-v1", RTT_TOOL_CHAIN: "sourcery-arm"} 117 | - {RTT_BSP: "stm32/stm32f767-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 118 | - {RTT_BSP: "stm32/stm32f769-st-disco", RTT_TOOL_CHAIN: "sourcery-arm"} 119 | - {RTT_BSP: "stm32/stm32g070-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 120 | - {RTT_BSP: "stm32/stm32g071-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 121 | - {RTT_BSP: "stm32/stm32g431-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 122 | - {RTT_BSP: "stm32/stm32g474-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 123 | - {RTT_BSP: "stm32/stm32h743-armfly-v7", RTT_TOOL_CHAIN: "sourcery-arm"} 124 | - {RTT_BSP: "stm32/stm32h743-atk-apollo", RTT_TOOL_CHAIN: "sourcery-arm"} 125 | - {RTT_BSP: "stm32/stm32h743-openmv-h7plus", RTT_TOOL_CHAIN: "sourcery-arm"} 126 | - {RTT_BSP: "stm32/stm32h743-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 127 | - {RTT_BSP: "stm32/stm32h747-st-discovery", RTT_TOOL_CHAIN: "sourcery-arm"} 128 | - {RTT_BSP: "stm32/stm32h750-artpi", RTT_TOOL_CHAIN: "sourcery-arm"} 129 | - {RTT_BSP: "stm32/stm32l4r5-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 130 | - {RTT_BSP: "stm32/stm32l4r9-st-eval", RTT_TOOL_CHAIN: "sourcery-arm"} 131 | - {RTT_BSP: "stm32/stm32l4r9-st-sensortile-box", RTT_TOOL_CHAIN: "sourcery-arm"} 132 | - {RTT_BSP: "stm32/stm32l010-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 133 | - {RTT_BSP: "stm32/stm32l053-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 134 | - {RTT_BSP: "stm32/stm32l412-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 135 | - {RTT_BSP: "stm32/stm32l431-BearPi", RTT_TOOL_CHAIN: "sourcery-arm"} 136 | - {RTT_BSP: "stm32/stm32l432-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 137 | - {RTT_BSP: "stm32/stm32l433-ali-startkit", RTT_TOOL_CHAIN: "sourcery-arm"} 138 | - {RTT_BSP: "stm32/stm32l433-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 139 | - {RTT_BSP: "stm32/stm32l452-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 140 | - {RTT_BSP: "stm32/stm32l475-atk-pandora", RTT_TOOL_CHAIN: "sourcery-arm"} 141 | - {RTT_BSP: "stm32/stm32l475-st-discovery", RTT_TOOL_CHAIN: "sourcery-arm"} 142 | - {RTT_BSP: "stm32/stm32l476-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 143 | - {RTT_BSP: "stm32/stm32l496-ali-developer", RTT_TOOL_CHAIN: "sourcery-arm"} 144 | - {RTT_BSP: "stm32/stm32l496-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 145 | - {RTT_BSP: "stm32/stm32l552-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 146 | - {RTT_BSP: "stm32/stm32mp157a-st-discovery", RTT_TOOL_CHAIN: "sourcery-arm"} 147 | - {RTT_BSP: "stm32/stm32mp157a-st-ev1", RTT_TOOL_CHAIN: "sourcery-arm"} 148 | - {RTT_BSP: "stm32/stm32u575-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 149 | - {RTT_BSP: "stm32/stm32wb55-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} 150 | - {RTT_BSP: "wch/arm/ch32f103c8-core", RTT_TOOL_CHAIN: "sourcery-arm"} 151 | - {RTT_BSP: "wch/arm/ch32f203r-evt", RTT_TOOL_CHAIN: "sourcery-arm"} 152 | - {RTT_BSP: "synwit/swm320", RTT_TOOL_CHAIN: "sourcery-arm"} 153 | - {RTT_BSP: "synwit/swm341", RTT_TOOL_CHAIN: "sourcery-arm"} 154 | - {RTT_BSP: "beaglebone", RTT_TOOL_CHAIN: "sourcery-arm"} 155 | - {RTT_BSP: "zynqmp-r5-axu4ev", RTT_TOOL_CHAIN: "sourcery-arm"} 156 | - {RTT_BSP: "frdm-k64f", RTT_TOOL_CHAIN: "sourcery-arm"} 157 | - {RTT_BSP: "at32/at32f403a-start", RTT_TOOL_CHAIN: "sourcery-arm"} 158 | - {RTT_BSP: "at32/at32f407-start", RTT_TOOL_CHAIN: "sourcery-arm"} 159 | - {RTT_BSP: "at32/at32f413-start", RTT_TOOL_CHAIN: "sourcery-arm"} 160 | - {RTT_BSP: "at32/at32f415-start", RTT_TOOL_CHAIN: "sourcery-arm"} 161 | - {RTT_BSP: "at32/at32f435-start", RTT_TOOL_CHAIN: "sourcery-arm"} 162 | - {RTT_BSP: "at32/at32f437-start", RTT_TOOL_CHAIN: "sourcery-arm"} 163 | - {RTT_BSP: "smartfusion2", RTT_TOOL_CHAIN: "sourcery-arm"} 164 | - {RTT_BSP: "raspberry-pico", RTT_TOOL_CHAIN: "sourcery-arm"} 165 | - {RTT_BSP: "hc32/ev_hc32f4a0_lqfp176", RTT_TOOL_CHAIN: "sourcery-arm"} 166 | - {RTT_BSP: "hc32/ev_hc32f460_lqfp100_v2", RTT_TOOL_CHAIN: "sourcery-arm"} 167 | - {RTT_BSP: "hc32l196", RTT_TOOL_CHAIN: "sourcery-arm"} 168 | - {RTT_BSP: "tae32f5300", RTT_TOOL_CHAIN: "sourcery-arm"} 169 | - {RTT_BSP: "microchip/samc21", RTT_TOOL_CHAIN: "sourcery-arm"} 170 | - {RTT_BSP: "microchip/same54", RTT_TOOL_CHAIN: "sourcery-arm"} 171 | - {RTT_BSP: "microchip/same70", RTT_TOOL_CHAIN: "sourcery-arm"} 172 | 173 | steps: 174 | - uses: actions/checkout@v3 175 | with: 176 | repository: RT-Thread/rt-thread 177 | branches: 'lts-v4.1.x' 178 | - name: Set up Python 179 | uses: actions/setup-python@v3 180 | with: 181 | python-version: 3.8 182 | 183 | - name: Install Tools 184 | shell: bash 185 | run: | 186 | sudo apt-get update 187 | sudo apt-get -qq install gcc-multilib libncurses5-dev scons 188 | sudo python -m pip install --upgrade pip -qq 189 | pip install requests -qq 190 | git config --global http.postBuffer 524288000 191 | python -c "import tools.menuconfig; tools.menuconfig.touch_env()" 192 | echo "RTT_ROOT=${{ github.workspace }}" >> $GITHUB_ENV 193 | echo "RTT_CC=gcc" >> $GITHUB_ENV 194 | 195 | - name: Install Arm ToolChains 196 | if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-arm' && success() }} 197 | shell: bash 198 | run: | 199 | wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.3/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 200 | sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt 201 | /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version 202 | echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin" >> $GITHUB_ENV 203 | 204 | - name: Bsp Scons Compile 205 | if: ${{ success() }} 206 | shell: bash 207 | env: 208 | RTT_BSP: ${{ matrix.legs.RTT_BSP }} 209 | RTT_TOOL_CHAIN: ${{ matrix.legs.RTT_TOOL_CHAIN }} 210 | run: | 211 | source ~/.env/env.sh 212 | du -h --max-depth=1 | sort -nr 213 | du -h --max-depth=1 bsp | sort -nr 214 | du -s * | sort -nr 215 | sed -i "s/# CONFIG_PKG_USING_SEGGER_RTT is not set/CONFIG_PKG_USING_SEGGER_RTT=y/g" bsp/$RTT_BSP/.config 216 | scons --pyconfig-silent -C bsp/$RTT_BSP 217 | cat bsp/$RTT_BSP/.config 218 | pushd bsp/$RTT_BSP && pkgs --update && popd 219 | scons -C bsp/$RTT_BSP 220 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | 2 | # Kconfig file for package SEGGER_RTT 3 | menuconfig PKG_USING_SEGGER_RTT 4 | bool "SEGGER_RTT:the RTT of segger jlink instead of uart of console" 5 | default n 6 | 7 | if PKG_USING_SEGGER_RTT 8 | 9 | choice 10 | prompt "Console type" 11 | default SEGGER_RTT_ENABLE 12 | help 13 | Select the transport type 14 | 15 | config SEGGER_RTT_ENABLE 16 | bool "Jlink SEGGER RTT support" 17 | 18 | config SWO_ENABLE 19 | bool "ARM CORTEX M SWO support" 20 | 21 | endchoice 22 | 23 | config SEGGER_RTT_MAX_NUM_UP_BUFFERS 24 | int "SEGGER_RTT_MAX_NUM_UP_BUFFERS" 25 | depends on SEGGER_RTT_ENABLE 26 | help 27 | Max. number of up-buffers (T->H) available on this target (Default: 3) 28 | default 3 29 | config SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 30 | int "SEGGER_RTT_MAX_NUM_DOWN_BUFFERS" 31 | depends on SEGGER_RTT_ENABLE 32 | help 33 | Max. number of down-buffers (H->T) available on this target (Default: 3) 34 | default 3 35 | 36 | config BUFFER_SIZE_UP 37 | int "BUFFER_SIZE_UP" 38 | depends on SEGGER_RTT_ENABLE 39 | help 40 | Size of the buffer for terminal output of target, up to host (Default: 1k) 41 | default 1024 42 | config BUFFER_SIZE_DOWN 43 | int "BUFFER_SIZE_DOWN" 44 | depends on SEGGER_RTT_ENABLE 45 | help 46 | Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) 47 | default 16 48 | config SEGGER_RTT_PRINTF_BUFFER_SIZE 49 | int "SEGGER_RTT_PRINTF_BUFFER_SIZE" 50 | depends on SEGGER_RTT_ENABLE 51 | help 52 | Size of buffer for RTT printf to bulk-send chars via RTT 53 | default 64 54 | 55 | config RTT_DEFAULT_BUFFER_INDEX 56 | int "RTT_DEFAULT_BUFFER_INDEX" 57 | depends on SEGGER_RTT_ENABLE 58 | default 0 59 | 60 | config RTT_DEFAULT_TERMINAL_INDEX 61 | int "RTT_DEFAULT_TERMINAL_INDEX" 62 | depends on SEGGER_RTT_ENABLE 63 | default 0 64 | 65 | 66 | 67 | config SWO_PORT_NUMBER 68 | int "SWO port number" 69 | depends on SWO_ENABLE 70 | default 0 71 | 72 | 73 | config PKG_SEGGER_RTT_PATH 74 | string 75 | default "/packages/tools/SEGGER_RTT" 76 | 77 | choice 78 | prompt "Version" 79 | default PKG_USING_SEGGER_RTT_LATEST_VERSION 80 | help 81 | Select the package version 82 | 83 | config PKG_USING_SEGGER_RTT_V100 84 | bool "v1.0.0" 85 | 86 | config PKG_USING_SEGGER_RTT_V110 87 | bool "v1.1.0" 88 | 89 | config PKG_USING_SEGGER_RTT_LATEST_VERSION 90 | bool "latest" 91 | endchoice 92 | 93 | config PKG_SEGGER_RTT_VER 94 | string 95 | default "v1.0.0" if PKG_USING_SEGGER_RTT_V100 96 | default "v1.1.0" if PKG_USING_SEGGER_RTT_V110 97 | default "latest" if PKG_USING_SEGGER_RTT_LATEST_VERSION 98 | 99 | endif 100 | 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RTTHREAD_SEGGER_TOOL 2 | 3 | # 如果觉得有用,欢迎点个右上角的star小星星⭐ 4 | 5 | ## Introduce 6 | 7 | 这个软件包主要将JLINK作为RTT 的console口来使用,能够节省一些设备的UART资源。该软件包必须依赖于JLINK之上的,手上必须要有JLINK相关的硬件调试器才能使用。 8 | 9 | SEGGER_RTT有以下几个特点: 10 | 11 | - 可以在中断中打印 12 | - 可以缓存开机的log 13 | - 可以接收命令 14 | - 多平台支持 15 | - 不依赖操作系统,单机裸机都可以运行SEGGER_printf 16 | - 支持SERIAL_V2 17 | 18 | ## 如何使用 19 | 20 | #### RTTHREAD串口框架SERIAL_V2 21 | 22 | 如果你的串口框架使用的是第二代串口框架的话`RT_USING_SERIAL_V2` 由于第二代串口框架非常依赖系统的调度,所以开始的`version`等信息无法打印出来(除非修改内核代码),不过只有这一个缺点,其他的命令行等都可以使用。只要使用的串口框架SERIAL_V2,打开配置`RT_USING_SERIAL_V2`既可以直接使用 23 | 24 | jlink在系统调度起来之后,会运行下面代码自动启动 25 | 26 | ``` 27 | int rt_hw_jlink_console_init(void) 28 | { 29 | rt_hw_jlink_rtt_init(); 30 | rt_console_set_device("jlinkRtt"); 31 | return 0; 32 | } 33 | INIT_APP_EXPORT(rt_hw_jlink_console_init); 34 | ``` 35 | `注意:如果终端打印提示[warning: tidle0 stack is close to end of stack address.],请在rtconfig.h文件中搜索IDLE_THREAD_STACK_SIZE,并扩大该栈空间` 36 | 37 | #### RTTHREAD串口框架SERIAL_V1 38 | 39 | 如果你的串口框架使用的是第一代串口框架的话`RT_USING_SERIAL_V1` , 如果你想打印调度前的version等信息的话,参考如下设置方法: 40 | 41 | drv_rtt.c 相当于多了一个UART串口device设备,如果你想要代替console的话,需要做如下修改 42 | 43 | - rt_hw_jlink_rtt_init 初始化必须在`rt_console_set_device(RT_CONSOLE_DEVICE_NAME);` 之前调用 44 | 45 | - rtconfig中的console也要设置为`jlinkRtt` 46 | 47 | ``` 48 | #define RT_CONSOLE_DEVICE_NAME "jlinkRtt" 49 | rt_hw_jlink_rtt_init(); 50 | rt_console_set_device(RT_CONSOLE_DEVICE_NAME); 51 | ``` 52 | 53 | 实现这两点,基本可以将console设置为segger_rtt 54 | 55 | 56 | 57 | ### JLINK_RTT_VIEWER配置 58 | 59 | 根据你当前的芯片以及JTAG还是SWD来选择 60 | 61 | ![image-20210523144320179](images/image-20210523144320179.png) 62 | 63 | 这边需要注意的是最下面的地址,指的是代码中`_SEGGER_RTT`的地址,有些芯片支持自动识别地址,有些芯片不支持自动识别地址。不支持的可以设置search 范围 64 | 65 | ``` 66 | 0x20000000 0x1000 67 | ``` 68 | 69 | ### SEGGER_RTT 地址 70 | 71 | segger_rtt的地址,这边通过修改代码,将地址默认设置在0x20000000上面,目前只支持KEIL这样做,后面会支持其他的,其他编译器需要debug的时候看下_SEGGER_RTT变量的地址。 72 | 73 | ``` 74 | SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT))__attribute__((section(".ARM.__at_0x20000000"))); 75 | ``` 76 | 77 | ## 高级使用技巧 78 | 79 | 可以在RTT viewer 连上之后,打开putty 80 | 81 | 配置如下: 82 | 83 | ![image-20210523144722163](images/image-20210523144722163.png) 84 | 85 | ![image-20210523145133760](images/image-20210523145133760.png) 86 | 87 | 也可以在RTT_VIEWER里面输入,putty和VIEWER只能用一种。输入Enter或者回车可以输入命令 88 | 89 | ![image-20210523145349136](images/image-20210523145349136.png) 90 | 91 | 需要注意输入方式要改成如下图所示的方式 92 | 93 | ![image-20221007203535784](images/image-20221007203535784.png) 94 | 95 | 96 | 97 | ## 注意事项 98 | 99 | 1. 你需要有JLINK连接。 在STM32或者nordic开发板上测试都是可以用的。其他的JLINK应该也是通用的,这个省去了调试的UART串口的占用。可以用这个口打印log或者console调试。当前前提是得有JLINK相应的硬件。 100 | 101 | 2. 只要你的开发板可以用JLINK来调试查看变量,就可以用这个软件包。 102 | RTT本质上,就是一直轮询_SEGGER_RTT这个全局变量。所以对架构不是特别敏感,只要你的板子JLINK可以debug即可。 103 | 104 | 3. 如果你手上有STLINK, 可以选择刷成JLINK 参考连接[segger st-link](https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/) 105 | 当然刷成JLINK之后,你的JLINK也只能操作STM32授权的设备,其他厂商设备是不支持的。 106 | 107 | 108 | 109 | 110 | ## 结语 111 | 112 | 这个是初步版本,如果有什么值得改进,或者建议,可以提issue或者直接PR。都是欢迎大家的。 113 | 114 | 115 | 116 | # SWO的使用 117 | 118 | SWO 的使用方法更加简单,原理和RTT一样,而且也可以实现TX RX。我之前一直以为,SWO只有要一根线,只能实现TX, 后来觉得有些奇怪,就查了下相关资料。发现也是可以实现RX的。那也就可以替代串口的console了。如下图所示。 119 | 120 | ![image-20210525025001074](images/image-20210525025001074.png) 121 | 122 | SWO的打印有以下几种方式,通常IDE一般都有支持: 123 | 124 | - KEIL debug(printf)打印 (可以实现TX RX) 125 | - IAR Terminal IO 打印 (可以实现TX RX) 126 | - JLINK SWO VIEWER (只能显示, 只能用于J-LINK) 127 | - ST-LINK SERIAL WIRE VIEWER (只能显示,只能用于ST-LINK) 128 | 129 | SWO 使用了ITM模块 130 | 131 | ## keil的使用方法 132 | 133 | keil中可以通过设置DEBUG来配置 134 | 135 | ![image-20210525030747681](images/image-20210525030747681.png) 136 | 137 | 设置完了之后,端口0就可以用了,如果使用其他端口,需要修改tx函数。debug的时候,打开debug(printf)的窗口,即可使用,这边要设置时钟和MCU中的时钟要一致,端口默认选择port0。 138 | 139 | 如果要实现console功能,如上面一开始讲到的一样 140 | 141 | - rt_hw_swo_init初始化必须在`rt_console_set_device(RT_CONSOLE_DEVICE_NAME);` 之前调用 142 | 143 | - rtconfig中的console也要设置为`SWO` 144 | 145 | ## IAR使用方法 146 | 147 | 打开SWO 148 | 149 | ![image-20210529222625567](images/image-20210529222625567.png) 150 | 151 | ![image-20210529222806327](images/image-20210529222806327.png) 152 | 153 | 154 | 155 | ![image-20210529222831650](images/image-20210529222831650.png) 156 | 157 | 158 | 159 | 参考文档中心文档: 160 | 161 | [SEGGER_RTT](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/application-note/debug/seggerRTT/segger_rtt) 162 | 163 | -------------------------------------------------------------------------------- /RTT/SEGGER_RTT.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2021 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | * * 45 | * RTT version: 7.20a * 46 | * * 47 | ********************************************************************** 48 | 49 | ---------------------------END-OF-HEADER------------------------------ 50 | File : SEGGER_RTT.c 51 | Purpose : Implementation of SEGGER real-time transfer (RTT) which 52 | allows real-time communication on targets which support 53 | debugger memory accesses while the CPU is running. 54 | Revision: $Rev: 22333 $ 55 | 56 | Additional information: 57 | Type "int" is assumed to be 32-bits in size 58 | H->T Host to target communication 59 | T->H Target to host communication 60 | 61 | RTT channel 0 is always present and reserved for Terminal usage. 62 | Name is fixed to "Terminal" 63 | 64 | Effective buffer size: SizeOfBuffer - 1 65 | 66 | WrOff == RdOff: Buffer is empty 67 | WrOff == (RdOff - 1): Buffer is full 68 | WrOff > RdOff: Free space includes wrap-around 69 | WrOff < RdOff: Used space includes wrap-around 70 | (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): 71 | Buffer full and wrap-around after next byte 72 | 73 | 74 | ---------------------------------------------------------------------- 75 | */ 76 | 77 | #include "SEGGER_RTT.h" 78 | 79 | #include // for memcpy 80 | 81 | /********************************************************************* 82 | * 83 | * Configuration, default values 84 | * 85 | ********************************************************************** 86 | */ 87 | 88 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 89 | #ifdef SEGGER_RTT_CB_ALIGN 90 | #error "Custom SEGGER_RTT_CB_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 91 | #endif 92 | #ifdef SEGGER_RTT_BUFFER_ALIGN 93 | #error "Custom SEGGER_RTT_BUFFER_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 94 | #endif 95 | #ifdef SEGGER_RTT_PUT_CB_SECTION 96 | #error "Custom SEGGER_RTT_PUT_CB_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 97 | #endif 98 | #ifdef SEGGER_RTT_PUT_BUFFER_SECTION 99 | #error "Custom SEGGER_RTT_PUT_BUFFER_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 100 | #endif 101 | #ifdef SEGGER_RTT_BUFFER_ALIGNMENT 102 | #error "Custom SEGGER_RTT_BUFFER_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 103 | #endif 104 | #ifdef SEGGER_RTT_ALIGNMENT 105 | #error "Custom SEGGER_RTT_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 106 | #endif 107 | #endif 108 | 109 | #ifndef BUFFER_SIZE_UP 110 | #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host 111 | #endif 112 | 113 | #ifndef BUFFER_SIZE_DOWN 114 | #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) 115 | #endif 116 | 117 | #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 118 | #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target 119 | #endif 120 | 121 | #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 122 | #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target 123 | #endif 124 | 125 | #ifndef SEGGER_RTT_BUFFER_SECTION 126 | #if defined(SEGGER_RTT_SECTION) 127 | #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION 128 | #endif 129 | #endif 130 | 131 | #ifndef SEGGER_RTT_ALIGNMENT 132 | #define SEGGER_RTT_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE 133 | #endif 134 | 135 | #ifndef SEGGER_RTT_BUFFER_ALIGNMENT 136 | #define SEGGER_RTT_BUFFER_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE 137 | #endif 138 | 139 | #ifndef SEGGER_RTT_MODE_DEFAULT 140 | #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP 141 | #endif 142 | 143 | #ifndef SEGGER_RTT_LOCK 144 | #define SEGGER_RTT_LOCK() 145 | #endif 146 | 147 | #ifndef SEGGER_RTT_UNLOCK 148 | #define SEGGER_RTT_UNLOCK() 149 | #endif 150 | 151 | #ifndef STRLEN 152 | #define STRLEN(a) strlen((a)) 153 | #endif 154 | 155 | #ifndef STRCPY 156 | #define STRCPY(pDest, pSrc) strcpy((pDest), (pSrc)) 157 | #endif 158 | 159 | #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP 160 | #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 161 | #endif 162 | 163 | #ifndef SEGGER_RTT_MEMCPY 164 | #ifdef MEMCPY 165 | #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) 166 | #else 167 | #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) 168 | #endif 169 | #endif 170 | 171 | #ifndef MIN 172 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 173 | #endif 174 | 175 | #ifndef MAX 176 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 177 | #endif 178 | // 179 | // For some environments, NULL may not be defined until certain headers are included 180 | // 181 | #ifndef NULL 182 | #define NULL 0 183 | #endif 184 | 185 | /********************************************************************* 186 | * 187 | * Defines, fixed 188 | * 189 | ********************************************************************** 190 | */ 191 | #if (defined __ICCARM__) || (defined __ICCRX__) 192 | #define RTT_PRAGMA(P) _Pragma(#P) 193 | #endif 194 | 195 | #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT 196 | #if (defined __GNUC__) 197 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 198 | #elif (defined __ICCARM__) || (defined __ICCRX__) 199 | #define PRAGMA(A) _Pragma(#A) 200 | #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ 201 | Var 202 | #elif (defined __CC_ARM) 203 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 204 | #else 205 | #error "Alignment not supported for this compiler." 206 | #endif 207 | #else 208 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var 209 | #endif 210 | 211 | #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) 212 | #if (defined __GNUC__) 213 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var 214 | #elif (defined __ICCARM__) || (defined __ICCRX__) 215 | #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ 216 | Var 217 | #elif (defined __CC_ARM) 218 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var 219 | #else 220 | #error "Section placement not supported for this compiler." 221 | #endif 222 | #else 223 | #define SEGGER_RTT_PUT_SECTION(Var, Section) Var 224 | #endif 225 | 226 | #if SEGGER_RTT_ALIGNMENT 227 | #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) 228 | #else 229 | #define SEGGER_RTT_CB_ALIGN(Var) Var 230 | #endif 231 | 232 | #if SEGGER_RTT_BUFFER_ALIGNMENT 233 | #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) 234 | #else 235 | #define SEGGER_RTT_BUFFER_ALIGN(Var) Var 236 | #endif 237 | 238 | 239 | #if defined(SEGGER_RTT_SECTION) 240 | #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) 241 | #else 242 | #define SEGGER_RTT_PUT_CB_SECTION(Var) Var 243 | #endif 244 | 245 | #if defined(SEGGER_RTT_BUFFER_SECTION) 246 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) 247 | #else 248 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var 249 | #endif 250 | 251 | /********************************************************************* 252 | * 253 | * Static const data 254 | * 255 | ********************************************************************** 256 | */ 257 | 258 | static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 259 | 260 | /********************************************************************* 261 | * 262 | * Static data 263 | * 264 | ********************************************************************** 265 | */ 266 | 267 | // 268 | // RTT Control Block and allocate buffers for channel 0 269 | // 270 | #if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */ 271 | SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));//这个可能存在问题,谨慎使用__attribute__((section(".ARM.__at_0x20000000"))); 272 | #else 273 | SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); 274 | #endif 275 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)])); 276 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)])); 277 | 278 | static unsigned char _ActiveTerminal; 279 | 280 | /********************************************************************* 281 | * 282 | * Static functions 283 | * 284 | ********************************************************************** 285 | */ 286 | 287 | /********************************************************************* 288 | * 289 | * _DoInit() 290 | * 291 | * Function description 292 | * Initializes the control block an buffers. 293 | * May only be called via INIT() to avoid overriding settings. 294 | * 295 | */ 296 | #define INIT() { \ 297 | volatile SEGGER_RTT_CB* pRTTCBInit; \ 298 | pRTTCBInit = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \ 299 | do { \ 300 | if (pRTTCBInit->acID[0] == '\0') { \ 301 | _DoInit(); \ 302 | } \ 303 | } while (0); \ 304 | } 305 | 306 | static void _DoInit(void) { 307 | volatile SEGGER_RTT_CB* p; // Volatile to make sure that compiler cannot change the order of accesses to the control block 308 | // 309 | // Initialize control block 310 | // 311 | p = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access control block uncached so that nothing in the cache ever becomes dirty and all changes are visible in HW directly 312 | p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; 313 | p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; 314 | // 315 | // Initialize up buffer 0 316 | // 317 | p->aUp[0].sName = "Terminal"; 318 | p->aUp[0].pBuffer = _acUpBuffer; 319 | p->aUp[0].SizeOfBuffer = BUFFER_SIZE_UP; 320 | p->aUp[0].RdOff = 0u; 321 | p->aUp[0].WrOff = 0u; 322 | p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; 323 | // 324 | // Initialize down buffer 0 325 | // 326 | p->aDown[0].sName = "Terminal"; 327 | p->aDown[0].pBuffer = _acDownBuffer; 328 | p->aDown[0].SizeOfBuffer = BUFFER_SIZE_DOWN; 329 | p->aDown[0].RdOff = 0u; 330 | p->aDown[0].WrOff = 0u; 331 | p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; 332 | // 333 | // Finish initialization of the control block. 334 | // Copy Id string in three steps to make sure "SEGGER RTT" is not found 335 | // in initializer memory (usually flash) by J-Link 336 | // 337 | STRCPY((char*)&p->acID[7], "RTT"); 338 | RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order 339 | STRCPY((char*)&p->acID[0], "SEGGER"); 340 | RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order 341 | p->acID[6] = ' '; 342 | RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order 343 | } 344 | 345 | /********************************************************************* 346 | * 347 | * _WriteBlocking() 348 | * 349 | * Function description 350 | * Stores a specified number of characters in SEGGER RTT ring buffer 351 | * and updates the associated write pointer which is periodically 352 | * read by the host. 353 | * The caller is responsible for managing the write chunk sizes as 354 | * _WriteBlocking() will block until all data has been posted successfully. 355 | * 356 | * Parameters 357 | * pRing Ring buffer to post to. 358 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 359 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 360 | * 361 | * Return value 362 | * >= 0 - Number of bytes written into buffer. 363 | */ 364 | static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { 365 | unsigned NumBytesToWrite; 366 | unsigned NumBytesWritten; 367 | unsigned RdOff; 368 | unsigned WrOff; 369 | volatile char* pDst; 370 | // 371 | // Write data to buffer and handle wrap-around if necessary 372 | // 373 | NumBytesWritten = 0u; 374 | WrOff = pRing->WrOff; 375 | do { 376 | RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime 377 | if (RdOff > WrOff) { 378 | NumBytesToWrite = RdOff - WrOff - 1u; 379 | } else { 380 | NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); 381 | } 382 | NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around 383 | NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); 384 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 385 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 386 | NumBytesWritten += NumBytesToWrite; 387 | NumBytes -= NumBytesToWrite; 388 | WrOff += NumBytesToWrite; 389 | while (NumBytesToWrite--) { 390 | *pDst++ = *pBuffer++; 391 | }; 392 | #else 393 | SEGGER_RTT_MEMCPY((void*)pDst, pBuffer, NumBytesToWrite); 394 | NumBytesWritten += NumBytesToWrite; 395 | pBuffer += NumBytesToWrite; 396 | NumBytes -= NumBytesToWrite; 397 | WrOff += NumBytesToWrite; 398 | #endif 399 | if (WrOff == pRing->SizeOfBuffer) { 400 | WrOff = 0u; 401 | } 402 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 403 | pRing->WrOff = WrOff; 404 | } while (NumBytes); 405 | return NumBytesWritten; 406 | } 407 | 408 | /********************************************************************* 409 | * 410 | * _WriteNoCheck() 411 | * 412 | * Function description 413 | * Stores a specified number of characters in SEGGER RTT ring buffer 414 | * and updates the associated write pointer which is periodically 415 | * read by the host. 416 | * It is callers responsibility to make sure data actually fits in buffer. 417 | * 418 | * Parameters 419 | * pRing Ring buffer to post to. 420 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 421 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 422 | * 423 | * Notes 424 | * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking 425 | */ 426 | static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { 427 | unsigned NumBytesAtOnce; 428 | unsigned WrOff; 429 | unsigned Rem; 430 | volatile char* pDst; 431 | 432 | WrOff = pRing->WrOff; 433 | Rem = pRing->SizeOfBuffer - WrOff; 434 | if (Rem > NumBytes) { 435 | // 436 | // All data fits before wrap around 437 | // 438 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 439 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 440 | WrOff += NumBytes; 441 | while (NumBytes--) { 442 | *pDst++ = *pData++; 443 | }; 444 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 445 | pRing->WrOff = WrOff; 446 | #else 447 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 448 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 449 | pRing->WrOff = WrOff + NumBytes; 450 | #endif 451 | } else { 452 | // 453 | // We reach the end of the buffer, so need to wrap around 454 | // 455 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 456 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 457 | NumBytesAtOnce = Rem; 458 | while (NumBytesAtOnce--) { 459 | *pDst++ = *pData++; 460 | }; 461 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 462 | NumBytesAtOnce = NumBytes - Rem; 463 | while (NumBytesAtOnce--) { 464 | *pDst++ = *pData++; 465 | }; 466 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 467 | pRing->WrOff = NumBytes - Rem; 468 | #else 469 | NumBytesAtOnce = Rem; 470 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 471 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytesAtOnce); 472 | NumBytesAtOnce = NumBytes - Rem; 473 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 474 | SEGGER_RTT_MEMCPY((void*)pDst, pData + Rem, NumBytesAtOnce); 475 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 476 | pRing->WrOff = NumBytesAtOnce; 477 | #endif 478 | } 479 | } 480 | 481 | /********************************************************************* 482 | * 483 | * _PostTerminalSwitch() 484 | * 485 | * Function description 486 | * Switch terminal to the given terminal ID. It is the caller's 487 | * responsibility to ensure the terminal ID is correct and there is 488 | * enough space in the buffer for this to complete successfully. 489 | * 490 | * Parameters 491 | * pRing Ring buffer to post to. 492 | * TerminalId Terminal ID to switch to. 493 | */ 494 | static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { 495 | unsigned char ac[2]; 496 | 497 | ac[0] = 0xFFu; 498 | ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit 499 | _WriteBlocking(pRing, (const char*)ac, 2u); 500 | } 501 | 502 | /********************************************************************* 503 | * 504 | * _GetAvailWriteSpace() 505 | * 506 | * Function description 507 | * Returns the number of bytes that can be written to the ring 508 | * buffer without blocking. 509 | * 510 | * Parameters 511 | * pRing Ring buffer to check. 512 | * 513 | * Return value 514 | * Number of bytes that are free in the buffer. 515 | */ 516 | static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { 517 | unsigned RdOff; 518 | unsigned WrOff; 519 | unsigned r; 520 | // 521 | // Avoid warnings regarding volatile access order. It's not a problem 522 | // in this case, but dampen compiler enthusiasm. 523 | // 524 | RdOff = pRing->RdOff; 525 | WrOff = pRing->WrOff; 526 | if (RdOff <= WrOff) { 527 | r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; 528 | } else { 529 | r = RdOff - WrOff - 1u; 530 | } 531 | return r; 532 | } 533 | 534 | /********************************************************************* 535 | * 536 | * Public code 537 | * 538 | ********************************************************************** 539 | */ 540 | 541 | /********************************************************************* 542 | * 543 | * SEGGER_RTT_ReadUpBufferNoLock() 544 | * 545 | * Function description 546 | * Reads characters from SEGGER real-time-terminal control block 547 | * which have been previously stored by the application. 548 | * Do not lock against interrupts and multiple access. 549 | * Used to do the same operation that J-Link does, to transfer 550 | * RTT data via other channels, such as TCP/IP or UART. 551 | * 552 | * Parameters 553 | * BufferIndex Index of Up-buffer to be used. 554 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 555 | * BufferSize Size of the target application buffer. 556 | * 557 | * Return value 558 | * Number of bytes that have been read. 559 | * 560 | * Additional information 561 | * This function must not be called when J-Link might also do RTT. 562 | */ 563 | unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 564 | unsigned NumBytesRem; 565 | unsigned NumBytesRead; 566 | unsigned RdOff; 567 | unsigned WrOff; 568 | unsigned char* pBuffer; 569 | SEGGER_RTT_BUFFER_UP* pRing; 570 | volatile char* pSrc; 571 | 572 | INIT(); 573 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 574 | pBuffer = (unsigned char*)pData; 575 | RdOff = pRing->RdOff; 576 | WrOff = pRing->WrOff; 577 | NumBytesRead = 0u; 578 | // 579 | // Read from current read position to wrap-around of buffer, first 580 | // 581 | if (RdOff > WrOff) { 582 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 583 | NumBytesRem = MIN(NumBytesRem, BufferSize); 584 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 585 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 586 | NumBytesRead += NumBytesRem; 587 | BufferSize -= NumBytesRem; 588 | RdOff += NumBytesRem; 589 | while (NumBytesRem--) { 590 | *pBuffer++ = *pSrc++; 591 | }; 592 | #else 593 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 594 | NumBytesRead += NumBytesRem; 595 | pBuffer += NumBytesRem; 596 | BufferSize -= NumBytesRem; 597 | RdOff += NumBytesRem; 598 | #endif 599 | // 600 | // Handle wrap-around of buffer 601 | // 602 | if (RdOff == pRing->SizeOfBuffer) { 603 | RdOff = 0u; 604 | } 605 | } 606 | // 607 | // Read remaining items of buffer 608 | // 609 | NumBytesRem = WrOff - RdOff; 610 | NumBytesRem = MIN(NumBytesRem, BufferSize); 611 | if (NumBytesRem > 0u) { 612 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 613 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 614 | NumBytesRead += NumBytesRem; 615 | BufferSize -= NumBytesRem; 616 | RdOff += NumBytesRem; 617 | while (NumBytesRem--) { 618 | *pBuffer++ = *pSrc++; 619 | }; 620 | #else 621 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 622 | NumBytesRead += NumBytesRem; 623 | pBuffer += NumBytesRem; 624 | BufferSize -= NumBytesRem; 625 | RdOff += NumBytesRem; 626 | #endif 627 | } 628 | // 629 | // Update read offset of buffer 630 | // 631 | if (NumBytesRead) { 632 | pRing->RdOff = RdOff; 633 | } 634 | // 635 | return NumBytesRead; 636 | } 637 | 638 | /********************************************************************* 639 | * 640 | * SEGGER_RTT_ReadNoLock() 641 | * 642 | * Function description 643 | * Reads characters from SEGGER real-time-terminal control block 644 | * which have been previously stored by the host. 645 | * Do not lock against interrupts and multiple access. 646 | * 647 | * Parameters 648 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 649 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 650 | * BufferSize Size of the target application buffer. 651 | * 652 | * Return value 653 | * Number of bytes that have been read. 654 | */ 655 | unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 656 | unsigned NumBytesRem; 657 | unsigned NumBytesRead; 658 | unsigned RdOff; 659 | unsigned WrOff; 660 | unsigned char* pBuffer; 661 | SEGGER_RTT_BUFFER_DOWN* pRing; 662 | volatile char* pSrc; 663 | // 664 | INIT(); 665 | pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 666 | pBuffer = (unsigned char*)pData; 667 | RdOff = pRing->RdOff; 668 | WrOff = pRing->WrOff; 669 | NumBytesRead = 0u; 670 | // 671 | // Read from current read position to wrap-around of buffer, first 672 | // 673 | if (RdOff > WrOff) { 674 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 675 | NumBytesRem = MIN(NumBytesRem, BufferSize); 676 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 677 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 678 | NumBytesRead += NumBytesRem; 679 | BufferSize -= NumBytesRem; 680 | RdOff += NumBytesRem; 681 | while (NumBytesRem--) { 682 | *pBuffer++ = *pSrc++; 683 | }; 684 | #else 685 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 686 | NumBytesRead += NumBytesRem; 687 | pBuffer += NumBytesRem; 688 | BufferSize -= NumBytesRem; 689 | RdOff += NumBytesRem; 690 | #endif 691 | // 692 | // Handle wrap-around of buffer 693 | // 694 | if (RdOff == pRing->SizeOfBuffer) { 695 | RdOff = 0u; 696 | } 697 | } 698 | // 699 | // Read remaining items of buffer 700 | // 701 | NumBytesRem = WrOff - RdOff; 702 | NumBytesRem = MIN(NumBytesRem, BufferSize); 703 | if (NumBytesRem > 0u) { 704 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 705 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 706 | NumBytesRead += NumBytesRem; 707 | BufferSize -= NumBytesRem; 708 | RdOff += NumBytesRem; 709 | while (NumBytesRem--) { 710 | *pBuffer++ = *pSrc++; 711 | }; 712 | #else 713 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 714 | NumBytesRead += NumBytesRem; 715 | pBuffer += NumBytesRem; 716 | BufferSize -= NumBytesRem; 717 | RdOff += NumBytesRem; 718 | #endif 719 | } 720 | if (NumBytesRead) { 721 | pRing->RdOff = RdOff; 722 | } 723 | // 724 | return NumBytesRead; 725 | } 726 | 727 | /********************************************************************* 728 | * 729 | * SEGGER_RTT_ReadUpBuffer 730 | * 731 | * Function description 732 | * Reads characters from SEGGER real-time-terminal control block 733 | * which have been previously stored by the application. 734 | * Used to do the same operation that J-Link does, to transfer 735 | * RTT data via other channels, such as TCP/IP or UART. 736 | * 737 | * Parameters 738 | * BufferIndex Index of Up-buffer to be used. 739 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 740 | * BufferSize Size of the target application buffer. 741 | * 742 | * Return value 743 | * Number of bytes that have been read. 744 | * 745 | * Additional information 746 | * This function must not be called when J-Link might also do RTT. 747 | * This function locks against all other RTT operations. I.e. during 748 | * the read operation, writing is also locked. 749 | * If only one consumer reads from the up buffer, 750 | * call sEGGER_RTT_ReadUpBufferNoLock() instead. 751 | */ 752 | unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 753 | unsigned NumBytesRead; 754 | 755 | SEGGER_RTT_LOCK(); 756 | // 757 | // Call the non-locking read function 758 | // 759 | NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); 760 | // 761 | // Finish up. 762 | // 763 | SEGGER_RTT_UNLOCK(); 764 | // 765 | return NumBytesRead; 766 | } 767 | 768 | /********************************************************************* 769 | * 770 | * SEGGER_RTT_Read 771 | * 772 | * Function description 773 | * Reads characters from SEGGER real-time-terminal control block 774 | * which have been previously stored by the host. 775 | * 776 | * Parameters 777 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 778 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 779 | * BufferSize Size of the target application buffer. 780 | * 781 | * Return value 782 | * Number of bytes that have been read. 783 | */ 784 | unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 785 | unsigned NumBytesRead; 786 | 787 | SEGGER_RTT_LOCK(); 788 | // 789 | // Call the non-locking read function 790 | // 791 | NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); 792 | // 793 | // Finish up. 794 | // 795 | SEGGER_RTT_UNLOCK(); 796 | // 797 | return NumBytesRead; 798 | } 799 | 800 | /********************************************************************* 801 | * 802 | * SEGGER_RTT_WriteWithOverwriteNoLock 803 | * 804 | * Function description 805 | * Stores a specified number of characters in SEGGER RTT 806 | * control block. 807 | * SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 808 | * and overwrites data if the data does not fit into the buffer. 809 | * 810 | * Parameters 811 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 812 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 813 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 814 | * 815 | * Notes 816 | * (1) If there is not enough space in the "Up"-buffer, data is overwritten. 817 | * (2) For performance reasons this function does not call Init() 818 | * and may only be called after RTT has been initialized. 819 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 820 | * (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 821 | * connection reads RTT data. 822 | */ 823 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 824 | const char* pData; 825 | SEGGER_RTT_BUFFER_UP* pRing; 826 | unsigned Avail; 827 | volatile char* pDst; 828 | // 829 | // Get "to-host" ring buffer and copy some elements into local variables. 830 | // 831 | pData = (const char *)pBuffer; 832 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 833 | // 834 | // Check if we will overwrite data and need to adjust the RdOff. 835 | // 836 | if (pRing->WrOff == pRing->RdOff) { 837 | Avail = pRing->SizeOfBuffer - 1u; 838 | } else if ( pRing->WrOff < pRing->RdOff) { 839 | Avail = pRing->RdOff - pRing->WrOff - 1u; 840 | } else { 841 | Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; 842 | } 843 | if (NumBytes > Avail) { 844 | pRing->RdOff += (NumBytes - Avail); 845 | while (pRing->RdOff >= pRing->SizeOfBuffer) { 846 | pRing->RdOff -= pRing->SizeOfBuffer; 847 | } 848 | } 849 | // 850 | // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds 851 | // 852 | Avail = pRing->SizeOfBuffer - pRing->WrOff; 853 | do { 854 | if (Avail > NumBytes) { 855 | // 856 | // Last round 857 | // 858 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 859 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 860 | Avail = NumBytes; 861 | while (NumBytes--) { 862 | *pDst++ = *pData++; 863 | }; 864 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 865 | pRing->WrOff += Avail; 866 | #else 867 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 868 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 869 | pRing->WrOff += NumBytes; 870 | #endif 871 | break; 872 | } else { 873 | // 874 | // Wrap-around necessary, write until wrap-around and reset WrOff 875 | // 876 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 877 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 878 | NumBytes -= Avail; 879 | while (Avail--) { 880 | *pDst++ = *pData++; 881 | }; 882 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 883 | pRing->WrOff = 0; 884 | #else 885 | SEGGER_RTT_MEMCPY((void*)pDst, pData, Avail); 886 | pData += Avail; 887 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 888 | pRing->WrOff = 0; 889 | NumBytes -= Avail; 890 | #endif 891 | Avail = (pRing->SizeOfBuffer - 1); 892 | } 893 | } while (NumBytes); 894 | } 895 | 896 | /********************************************************************* 897 | * 898 | * SEGGER_RTT_WriteSkipNoLock 899 | * 900 | * Function description 901 | * Stores a specified number of characters in SEGGER RTT 902 | * control block which is then read by the host. 903 | * SEGGER_RTT_WriteSkipNoLock does not lock the application and 904 | * skips all data, if the data does not fit into the buffer. 905 | * 906 | * Parameters 907 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 908 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 909 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 910 | * MUST be > 0!!! 911 | * This is done for performance reasons, so no initial check has do be done. 912 | * 913 | * Return value 914 | * 1: Data has been copied 915 | * 0: No space, data has not been copied 916 | * 917 | * Notes 918 | * (1) If there is not enough space in the "Up"-buffer, all data is dropped. 919 | * (2) For performance reasons this function does not call Init() 920 | * and may only be called after RTT has been initialized. 921 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 922 | */ 923 | #if (RTT_USE_ASM == 0) 924 | unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 925 | const char* pData; 926 | SEGGER_RTT_BUFFER_UP* pRing; 927 | unsigned Avail; 928 | unsigned RdOff; 929 | unsigned WrOff; 930 | unsigned Rem; 931 | volatile char* pDst; 932 | // 933 | // Cases: 934 | // 1) RdOff <= WrOff => Space until wrap-around is sufficient 935 | // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) 936 | // 3) RdOff < WrOff => No space in buf 937 | // 4) RdOff > WrOff => Space is sufficient 938 | // 5) RdOff > WrOff => No space in buf 939 | // 940 | // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough 941 | // 942 | pData = (const char *)pBuffer; 943 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 944 | RdOff = pRing->RdOff; 945 | WrOff = pRing->WrOff; 946 | if (RdOff <= WrOff) { // Case 1), 2) or 3) 947 | Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) 948 | if (Avail >= NumBytes) { // Case 1)? 949 | CopyStraight: 950 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 951 | memcpy((void*)pDst, pData, NumBytes); 952 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 953 | pRing->WrOff = WrOff + NumBytes; 954 | return 1; 955 | } 956 | Avail += RdOff; // Space incl. wrap-around 957 | if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) 958 | Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer 959 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 960 | memcpy((void*)pDst, pData, Rem); // Copy 1st chunk 961 | NumBytes -= Rem; 962 | // 963 | // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used 964 | // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element 965 | // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks 966 | // Therefore, check if 2nd memcpy is necessary at all 967 | // 968 | if (NumBytes) { 969 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 970 | memcpy((void*)pDst, pData + Rem, NumBytes); 971 | } 972 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 973 | pRing->WrOff = NumBytes; 974 | return 1; 975 | } 976 | } else { // Potential case 4) 977 | Avail = RdOff - WrOff - 1u; 978 | if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit) 979 | goto CopyStraight; 980 | } 981 | } 982 | return 0; // No space in buffer 983 | } 984 | #endif 985 | 986 | /********************************************************************* 987 | * 988 | * SEGGER_RTT_WriteDownBufferNoLock 989 | * 990 | * Function description 991 | * Stores a specified number of characters in SEGGER RTT 992 | * control block inside a buffer. 993 | * SEGGER_RTT_WriteDownBufferNoLock does not lock the application. 994 | * Used to do the same operation that J-Link does, to transfer 995 | * RTT data from other channels, such as TCP/IP or UART. 996 | * 997 | * Parameters 998 | * BufferIndex Index of "Down"-buffer to be used. 999 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1000 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1001 | * 1002 | * Return value 1003 | * Number of bytes which have been stored in the "Down"-buffer. 1004 | * 1005 | * Notes 1006 | * (1) Data is stored according to buffer flags. 1007 | * (2) For performance reasons this function does not call Init() 1008 | * and may only be called after RTT has been initialized. 1009 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1010 | * 1011 | * Additional information 1012 | * This function must not be called when J-Link might also do RTT. 1013 | */ 1014 | unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1015 | unsigned Status; 1016 | unsigned Avail; 1017 | const char* pData; 1018 | SEGGER_RTT_BUFFER_UP* pRing; 1019 | // 1020 | // Get "to-target" ring buffer. 1021 | // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link. 1022 | // 1023 | pData = (const char *)pBuffer; 1024 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1025 | // 1026 | // How we output depends upon the mode... 1027 | // 1028 | switch (pRing->Flags) { 1029 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1030 | // 1031 | // If we are in skip mode and there is no space for the whole 1032 | // of this output, don't bother. 1033 | // 1034 | Avail = _GetAvailWriteSpace(pRing); 1035 | if (Avail < NumBytes) { 1036 | Status = 0u; 1037 | } else { 1038 | Status = NumBytes; 1039 | _WriteNoCheck(pRing, pData, NumBytes); 1040 | } 1041 | break; 1042 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1043 | // 1044 | // If we are in trim mode, trim to what we can output without blocking. 1045 | // 1046 | Avail = _GetAvailWriteSpace(pRing); 1047 | Status = Avail < NumBytes ? Avail : NumBytes; 1048 | _WriteNoCheck(pRing, pData, Status); 1049 | break; 1050 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1051 | // 1052 | // If we are in blocking mode, output everything. 1053 | // 1054 | Status = _WriteBlocking(pRing, pData, NumBytes); 1055 | break; 1056 | default: 1057 | Status = 0u; 1058 | break; 1059 | } 1060 | // 1061 | // Finish up. 1062 | // 1063 | return Status; 1064 | } 1065 | 1066 | /********************************************************************* 1067 | * 1068 | * SEGGER_RTT_WriteNoLock 1069 | * 1070 | * Function description 1071 | * Stores a specified number of characters in SEGGER RTT 1072 | * control block which is then read by the host. 1073 | * SEGGER_RTT_WriteNoLock does not lock the application. 1074 | * 1075 | * Parameters 1076 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1077 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1078 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1079 | * 1080 | * Return value 1081 | * Number of bytes which have been stored in the "Up"-buffer. 1082 | * 1083 | * Notes 1084 | * (1) Data is stored according to buffer flags. 1085 | * (2) For performance reasons this function does not call Init() 1086 | * and may only be called after RTT has been initialized. 1087 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1088 | */ 1089 | unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1090 | unsigned Status; 1091 | unsigned Avail; 1092 | const char* pData; 1093 | SEGGER_RTT_BUFFER_UP* pRing; 1094 | // 1095 | // Get "to-host" ring buffer. 1096 | // 1097 | pData = (const char *)pBuffer; 1098 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1099 | // 1100 | // How we output depends upon the mode... 1101 | // 1102 | switch (pRing->Flags) { 1103 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1104 | // 1105 | // If we are in skip mode and there is no space for the whole 1106 | // of this output, don't bother. 1107 | // 1108 | Avail = _GetAvailWriteSpace(pRing); 1109 | if (Avail < NumBytes) { 1110 | Status = 0u; 1111 | } else { 1112 | Status = NumBytes; 1113 | _WriteNoCheck(pRing, pData, NumBytes); 1114 | } 1115 | break; 1116 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1117 | // 1118 | // If we are in trim mode, trim to what we can output without blocking. 1119 | // 1120 | Avail = _GetAvailWriteSpace(pRing); 1121 | Status = Avail < NumBytes ? Avail : NumBytes; 1122 | _WriteNoCheck(pRing, pData, Status); 1123 | break; 1124 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1125 | // 1126 | // If we are in blocking mode, output everything. 1127 | // 1128 | Status = _WriteBlocking(pRing, pData, NumBytes); 1129 | break; 1130 | default: 1131 | Status = 0u; 1132 | break; 1133 | } 1134 | // 1135 | // Finish up. 1136 | // 1137 | return Status; 1138 | } 1139 | 1140 | /********************************************************************* 1141 | * 1142 | * SEGGER_RTT_WriteDownBuffer 1143 | * 1144 | * Function description 1145 | * Stores a specified number of characters in SEGGER RTT control block in a buffer. 1146 | * 1147 | * Parameters 1148 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1149 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1150 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1151 | * 1152 | * Return value 1153 | * Number of bytes which have been stored in the "Down"-buffer. 1154 | * 1155 | * Notes 1156 | * (1) Data is stored according to buffer flags. 1157 | * 1158 | * Additional information 1159 | * This function must not be called when J-Link might also do RTT. 1160 | * This function locks against all other RTT operations. I.e. during 1161 | * the write operation, writing from the application is also locked. 1162 | * If only one consumer writes to the down buffer, 1163 | * call SEGGER_RTT_WriteDownBufferNoLock() instead. 1164 | */ 1165 | unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1166 | unsigned Status; 1167 | 1168 | INIT(); 1169 | SEGGER_RTT_LOCK(); 1170 | Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1171 | SEGGER_RTT_UNLOCK(); 1172 | return Status; 1173 | } 1174 | 1175 | /********************************************************************* 1176 | * 1177 | * SEGGER_RTT_Write 1178 | * 1179 | * Function description 1180 | * Stores a specified number of characters in SEGGER RTT 1181 | * control block which is then read by the host. 1182 | * 1183 | * Parameters 1184 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1185 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1186 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1187 | * 1188 | * Return value 1189 | * Number of bytes which have been stored in the "Up"-buffer. 1190 | * 1191 | * Notes 1192 | * (1) Data is stored according to buffer flags. 1193 | */ 1194 | unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1195 | unsigned Status; 1196 | 1197 | INIT(); 1198 | SEGGER_RTT_LOCK(); 1199 | Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1200 | SEGGER_RTT_UNLOCK(); 1201 | return Status; 1202 | } 1203 | 1204 | /********************************************************************* 1205 | * 1206 | * SEGGER_RTT_WriteString 1207 | * 1208 | * Function description 1209 | * Stores string in SEGGER RTT control block. 1210 | * This data is read by the host. 1211 | * 1212 | * Parameters 1213 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1214 | * s Pointer to string. 1215 | * 1216 | * Return value 1217 | * Number of bytes which have been stored in the "Up"-buffer. 1218 | * 1219 | * Notes 1220 | * (1) Data is stored according to buffer flags. 1221 | * (2) String passed to this function has to be \0 terminated 1222 | * (3) \0 termination character is *not* stored in RTT buffer 1223 | */ 1224 | unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { 1225 | unsigned Len; 1226 | 1227 | Len = STRLEN(s); 1228 | return SEGGER_RTT_Write(BufferIndex, s, Len); 1229 | } 1230 | 1231 | /********************************************************************* 1232 | * 1233 | * SEGGER_RTT_PutCharSkipNoLock 1234 | * 1235 | * Function description 1236 | * Stores a single character/byte in SEGGER RTT buffer. 1237 | * SEGGER_RTT_PutCharSkipNoLock does not lock the application and 1238 | * skips the byte, if it does not fit into the buffer. 1239 | * 1240 | * Parameters 1241 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1242 | * c Byte to be stored. 1243 | * 1244 | * Return value 1245 | * Number of bytes which have been stored in the "Up"-buffer. 1246 | * 1247 | * Notes 1248 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1249 | * (2) For performance reasons this function does not call Init() 1250 | * and may only be called after RTT has been initialized. 1251 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1252 | */ 1253 | 1254 | unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { 1255 | SEGGER_RTT_BUFFER_UP* pRing; 1256 | unsigned WrOff; 1257 | unsigned Status; 1258 | volatile char* pDst; 1259 | // 1260 | // Get "to-host" ring buffer. 1261 | // 1262 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1263 | // 1264 | // Get write position and handle wrap-around if necessary 1265 | // 1266 | WrOff = pRing->WrOff + 1; 1267 | if (WrOff == pRing->SizeOfBuffer) { 1268 | WrOff = 0; 1269 | } 1270 | // 1271 | // Output byte if free space is available 1272 | // 1273 | if (WrOff != pRing->RdOff) { 1274 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1275 | *pDst = c; 1276 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1277 | pRing->WrOff = WrOff; 1278 | Status = 1; 1279 | } else { 1280 | Status = 0; 1281 | } 1282 | // 1283 | return Status; 1284 | } 1285 | 1286 | /********************************************************************* 1287 | * 1288 | * SEGGER_RTT_PutCharSkip 1289 | * 1290 | * Function description 1291 | * Stores a single character/byte in SEGGER RTT buffer. 1292 | * 1293 | * Parameters 1294 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1295 | * c Byte to be stored. 1296 | * 1297 | * Return value 1298 | * Number of bytes which have been stored in the "Up"-buffer. 1299 | * 1300 | * Notes 1301 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1302 | */ 1303 | 1304 | unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { 1305 | SEGGER_RTT_BUFFER_UP* pRing; 1306 | unsigned WrOff; 1307 | unsigned Status; 1308 | volatile char* pDst; 1309 | // 1310 | // Prepare 1311 | // 1312 | INIT(); 1313 | SEGGER_RTT_LOCK(); 1314 | // 1315 | // Get "to-host" ring buffer. 1316 | // 1317 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1318 | // 1319 | // Get write position and handle wrap-around if necessary 1320 | // 1321 | WrOff = pRing->WrOff + 1; 1322 | if (WrOff == pRing->SizeOfBuffer) { 1323 | WrOff = 0; 1324 | } 1325 | // 1326 | // Output byte if free space is available 1327 | // 1328 | if (WrOff != pRing->RdOff) { 1329 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1330 | *pDst = c; 1331 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1332 | pRing->WrOff = WrOff; 1333 | Status = 1; 1334 | } else { 1335 | Status = 0; 1336 | } 1337 | // 1338 | // Finish up. 1339 | // 1340 | SEGGER_RTT_UNLOCK(); 1341 | // 1342 | return Status; 1343 | } 1344 | 1345 | /********************************************************************* 1346 | * 1347 | * SEGGER_RTT_PutChar 1348 | * 1349 | * Function description 1350 | * Stores a single character/byte in SEGGER RTT buffer. 1351 | * 1352 | * Parameters 1353 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1354 | * c Byte to be stored. 1355 | * 1356 | * Return value 1357 | * Number of bytes which have been stored in the "Up"-buffer. 1358 | * 1359 | * Notes 1360 | * (1) Data is stored according to buffer flags. 1361 | */ 1362 | 1363 | unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { 1364 | SEGGER_RTT_BUFFER_UP* pRing; 1365 | unsigned WrOff; 1366 | unsigned Status; 1367 | volatile char* pDst; 1368 | // 1369 | // Prepare 1370 | // 1371 | INIT(); 1372 | SEGGER_RTT_LOCK(); 1373 | // 1374 | // Get "to-host" ring buffer. 1375 | // 1376 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1377 | // 1378 | // Get write position and handle wrap-around if necessary 1379 | // 1380 | WrOff = pRing->WrOff + 1; 1381 | if (WrOff == pRing->SizeOfBuffer) { 1382 | WrOff = 0; 1383 | } 1384 | // 1385 | // Wait for free space if mode is set to blocking 1386 | // 1387 | if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1388 | while (WrOff == pRing->RdOff) { 1389 | ; 1390 | } 1391 | } 1392 | // 1393 | // Output byte if free space is available 1394 | // 1395 | if (WrOff != pRing->RdOff) { 1396 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1397 | *pDst = c; 1398 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1399 | pRing->WrOff = WrOff; 1400 | Status = 1; 1401 | } else { 1402 | Status = 0; 1403 | } 1404 | // 1405 | // Finish up. 1406 | // 1407 | SEGGER_RTT_UNLOCK(); 1408 | return Status; 1409 | } 1410 | 1411 | /********************************************************************* 1412 | * 1413 | * SEGGER_RTT_GetKey 1414 | * 1415 | * Function description 1416 | * Reads one character from the SEGGER RTT buffer. 1417 | * Host has previously stored data there. 1418 | * 1419 | * Return value 1420 | * < 0 - No character available (buffer empty). 1421 | * >= 0 - Character which has been read. (Possible values: 0 - 255) 1422 | * 1423 | * Notes 1424 | * (1) This function is only specified for accesses to RTT buffer 0. 1425 | */ 1426 | int SEGGER_RTT_GetKey(void) { 1427 | char c; 1428 | int r; 1429 | 1430 | r = (int)SEGGER_RTT_Read(0u, &c, 1u); 1431 | if (r == 1) { 1432 | r = (int)(unsigned char)c; 1433 | } else { 1434 | r = -1; 1435 | } 1436 | return r; 1437 | } 1438 | 1439 | /********************************************************************* 1440 | * 1441 | * SEGGER_RTT_WaitKey 1442 | * 1443 | * Function description 1444 | * Waits until at least one character is avaible in the SEGGER RTT buffer. 1445 | * Once a character is available, it is read and this function returns. 1446 | * 1447 | * Return value 1448 | * >=0 - Character which has been read. 1449 | * 1450 | * Notes 1451 | * (1) This function is only specified for accesses to RTT buffer 0 1452 | * (2) This function is blocking if no character is present in RTT buffer 1453 | */ 1454 | int SEGGER_RTT_WaitKey(void) { 1455 | int r; 1456 | 1457 | do { 1458 | r = SEGGER_RTT_GetKey(); 1459 | } while (r < 0); 1460 | return r; 1461 | } 1462 | 1463 | /********************************************************************* 1464 | * 1465 | * SEGGER_RTT_HasKey 1466 | * 1467 | * Function description 1468 | * Checks if at least one character for reading is available in the SEGGER RTT buffer. 1469 | * 1470 | * Return value 1471 | * == 0 - No characters are available to read. 1472 | * == 1 - At least one character is available. 1473 | * 1474 | * Notes 1475 | * (1) This function is only specified for accesses to RTT buffer 0 1476 | */ 1477 | int SEGGER_RTT_HasKey(void) { 1478 | SEGGER_RTT_BUFFER_DOWN* pRing; 1479 | unsigned RdOff; 1480 | int r; 1481 | 1482 | INIT(); 1483 | pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1484 | RdOff = pRing->RdOff; 1485 | if (RdOff != pRing->WrOff) { 1486 | r = 1; 1487 | } else { 1488 | r = 0; 1489 | } 1490 | return r; 1491 | } 1492 | 1493 | /********************************************************************* 1494 | * 1495 | * SEGGER_RTT_HasData 1496 | * 1497 | * Function description 1498 | * Check if there is data from the host in the given buffer. 1499 | * 1500 | * Return value: 1501 | * ==0: No data 1502 | * !=0: Data in buffer 1503 | * 1504 | */ 1505 | unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { 1506 | SEGGER_RTT_BUFFER_DOWN* pRing; 1507 | unsigned v; 1508 | 1509 | pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1510 | v = pRing->WrOff; 1511 | return v - pRing->RdOff; 1512 | } 1513 | 1514 | /********************************************************************* 1515 | * 1516 | * SEGGER_RTT_HasDataUp 1517 | * 1518 | * Function description 1519 | * Check if there is data remaining to be sent in the given buffer. 1520 | * 1521 | * Return value: 1522 | * ==0: No data 1523 | * !=0: Data in buffer 1524 | * 1525 | */ 1526 | unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { 1527 | SEGGER_RTT_BUFFER_UP* pRing; 1528 | unsigned v; 1529 | 1530 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1531 | v = pRing->RdOff; 1532 | return pRing->WrOff - v; 1533 | } 1534 | 1535 | /********************************************************************* 1536 | * 1537 | * SEGGER_RTT_AllocDownBuffer 1538 | * 1539 | * Function description 1540 | * Run-time configuration of the next down-buffer (H->T). 1541 | * The next buffer, which is not used yet is configured. 1542 | * This includes: Buffer address, size, name, flags, ... 1543 | * 1544 | * Parameters 1545 | * sName Pointer to a constant name string. 1546 | * pBuffer Pointer to a buffer to be used. 1547 | * BufferSize Size of the buffer. 1548 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1549 | * 1550 | * Return value 1551 | * >= 0 - O.K. Buffer Index 1552 | * < 0 - Error 1553 | */ 1554 | int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1555 | int BufferIndex; 1556 | volatile SEGGER_RTT_CB* pRTTCB; 1557 | 1558 | INIT(); 1559 | SEGGER_RTT_LOCK(); 1560 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1561 | BufferIndex = 0; 1562 | do { 1563 | if (pRTTCB->aDown[BufferIndex].pBuffer == NULL) { 1564 | break; 1565 | } 1566 | BufferIndex++; 1567 | } while (BufferIndex < pRTTCB->MaxNumDownBuffers); 1568 | if (BufferIndex < pRTTCB->MaxNumDownBuffers) { 1569 | pRTTCB->aDown[BufferIndex].sName = sName; 1570 | pRTTCB->aDown[BufferIndex].pBuffer = (char*)pBuffer; 1571 | pRTTCB->aDown[BufferIndex].SizeOfBuffer = BufferSize; 1572 | pRTTCB->aDown[BufferIndex].RdOff = 0u; 1573 | pRTTCB->aDown[BufferIndex].WrOff = 0u; 1574 | pRTTCB->aDown[BufferIndex].Flags = Flags; 1575 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1576 | } else { 1577 | BufferIndex = -1; 1578 | } 1579 | SEGGER_RTT_UNLOCK(); 1580 | return BufferIndex; 1581 | } 1582 | 1583 | /********************************************************************* 1584 | * 1585 | * SEGGER_RTT_AllocUpBuffer 1586 | * 1587 | * Function description 1588 | * Run-time configuration of the next up-buffer (T->H). 1589 | * The next buffer, which is not used yet is configured. 1590 | * This includes: Buffer address, size, name, flags, ... 1591 | * 1592 | * Parameters 1593 | * sName Pointer to a constant name string. 1594 | * pBuffer Pointer to a buffer to be used. 1595 | * BufferSize Size of the buffer. 1596 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1597 | * 1598 | * Return value 1599 | * >= 0 - O.K. Buffer Index 1600 | * < 0 - Error 1601 | */ 1602 | int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1603 | int BufferIndex; 1604 | volatile SEGGER_RTT_CB* pRTTCB; 1605 | 1606 | INIT(); 1607 | SEGGER_RTT_LOCK(); 1608 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1609 | BufferIndex = 0; 1610 | do { 1611 | if (pRTTCB->aUp[BufferIndex].pBuffer == NULL) { 1612 | break; 1613 | } 1614 | BufferIndex++; 1615 | } while (BufferIndex < pRTTCB->MaxNumUpBuffers); 1616 | if (BufferIndex < pRTTCB->MaxNumUpBuffers) { 1617 | pRTTCB->aUp[BufferIndex].sName = sName; 1618 | pRTTCB->aUp[BufferIndex].pBuffer = (char*)pBuffer; 1619 | pRTTCB->aUp[BufferIndex].SizeOfBuffer = BufferSize; 1620 | pRTTCB->aUp[BufferIndex].RdOff = 0u; 1621 | pRTTCB->aUp[BufferIndex].WrOff = 0u; 1622 | pRTTCB->aUp[BufferIndex].Flags = Flags; 1623 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1624 | } else { 1625 | BufferIndex = -1; 1626 | } 1627 | SEGGER_RTT_UNLOCK(); 1628 | return BufferIndex; 1629 | } 1630 | 1631 | /********************************************************************* 1632 | * 1633 | * SEGGER_RTT_ConfigUpBuffer 1634 | * 1635 | * Function description 1636 | * Run-time configuration of a specific up-buffer (T->H). 1637 | * Buffer to be configured is specified by index. 1638 | * This includes: Buffer address, size, name, flags, ... 1639 | * 1640 | * Parameters 1641 | * BufferIndex Index of the buffer to configure. 1642 | * sName Pointer to a constant name string. 1643 | * pBuffer Pointer to a buffer to be used. 1644 | * BufferSize Size of the buffer. 1645 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1646 | * 1647 | * Return value 1648 | * >= 0 - O.K. 1649 | * < 0 - Error 1650 | * 1651 | * Additional information 1652 | * Buffer 0 is configured on compile-time. 1653 | * May only be called once per buffer. 1654 | * Buffer name and flags can be reconfigured using the appropriate functions. 1655 | */ 1656 | int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1657 | int r; 1658 | volatile SEGGER_RTT_CB* pRTTCB; 1659 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1660 | 1661 | INIT(); 1662 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1663 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1664 | SEGGER_RTT_LOCK(); 1665 | pUp = &pRTTCB->aUp[BufferIndex]; 1666 | if (BufferIndex) { 1667 | pUp->sName = sName; 1668 | pUp->pBuffer = (char*)pBuffer; 1669 | pUp->SizeOfBuffer = BufferSize; 1670 | pUp->RdOff = 0u; 1671 | pUp->WrOff = 0u; 1672 | } 1673 | pUp->Flags = Flags; 1674 | SEGGER_RTT_UNLOCK(); 1675 | r = 0; 1676 | } else { 1677 | r = -1; 1678 | } 1679 | return r; 1680 | } 1681 | 1682 | /********************************************************************* 1683 | * 1684 | * SEGGER_RTT_ConfigDownBuffer 1685 | * 1686 | * Function description 1687 | * Run-time configuration of a specific down-buffer (H->T). 1688 | * Buffer to be configured is specified by index. 1689 | * This includes: Buffer address, size, name, flags, ... 1690 | * 1691 | * Parameters 1692 | * BufferIndex Index of the buffer to configure. 1693 | * sName Pointer to a constant name string. 1694 | * pBuffer Pointer to a buffer to be used. 1695 | * BufferSize Size of the buffer. 1696 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1697 | * 1698 | * Return value 1699 | * >= 0 O.K. 1700 | * < 0 Error 1701 | * 1702 | * Additional information 1703 | * Buffer 0 is configured on compile-time. 1704 | * May only be called once per buffer. 1705 | * Buffer name and flags can be reconfigured using the appropriate functions. 1706 | */ 1707 | int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1708 | int r; 1709 | volatile SEGGER_RTT_CB* pRTTCB; 1710 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1711 | 1712 | INIT(); 1713 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1714 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1715 | SEGGER_RTT_LOCK(); 1716 | pDown = &pRTTCB->aDown[BufferIndex]; 1717 | if (BufferIndex) { 1718 | pDown->sName = sName; 1719 | pDown->pBuffer = (char*)pBuffer; 1720 | pDown->SizeOfBuffer = BufferSize; 1721 | pDown->RdOff = 0u; 1722 | pDown->WrOff = 0u; 1723 | } 1724 | pDown->Flags = Flags; 1725 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1726 | SEGGER_RTT_UNLOCK(); 1727 | r = 0; 1728 | } else { 1729 | r = -1; 1730 | } 1731 | return r; 1732 | } 1733 | 1734 | /********************************************************************* 1735 | * 1736 | * SEGGER_RTT_SetNameUpBuffer 1737 | * 1738 | * Function description 1739 | * Run-time configuration of a specific up-buffer name (T->H). 1740 | * Buffer to be configured is specified by index. 1741 | * 1742 | * Parameters 1743 | * BufferIndex Index of the buffer to renamed. 1744 | * sName Pointer to a constant name string. 1745 | * 1746 | * Return value 1747 | * >= 0 O.K. 1748 | * < 0 Error 1749 | */ 1750 | int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { 1751 | int r; 1752 | volatile SEGGER_RTT_CB* pRTTCB; 1753 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1754 | 1755 | INIT(); 1756 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1757 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1758 | SEGGER_RTT_LOCK(); 1759 | pUp = &pRTTCB->aUp[BufferIndex]; 1760 | pUp->sName = sName; 1761 | SEGGER_RTT_UNLOCK(); 1762 | r = 0; 1763 | } else { 1764 | r = -1; 1765 | } 1766 | return r; 1767 | } 1768 | 1769 | /********************************************************************* 1770 | * 1771 | * SEGGER_RTT_SetNameDownBuffer 1772 | * 1773 | * Function description 1774 | * Run-time configuration of a specific Down-buffer name (T->H). 1775 | * Buffer to be configured is specified by index. 1776 | * 1777 | * Parameters 1778 | * BufferIndex Index of the buffer to renamed. 1779 | * sName Pointer to a constant name string. 1780 | * 1781 | * Return value 1782 | * >= 0 O.K. 1783 | * < 0 Error 1784 | */ 1785 | int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { 1786 | int r; 1787 | volatile SEGGER_RTT_CB* pRTTCB; 1788 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1789 | 1790 | INIT(); 1791 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1792 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1793 | SEGGER_RTT_LOCK(); 1794 | pDown = &pRTTCB->aDown[BufferIndex]; 1795 | pDown->sName = sName; 1796 | SEGGER_RTT_UNLOCK(); 1797 | r = 0; 1798 | } else { 1799 | r = -1; 1800 | } 1801 | return r; 1802 | } 1803 | 1804 | /********************************************************************* 1805 | * 1806 | * SEGGER_RTT_SetFlagsUpBuffer 1807 | * 1808 | * Function description 1809 | * Run-time configuration of specific up-buffer flags (T->H). 1810 | * Buffer to be configured is specified by index. 1811 | * 1812 | * Parameters 1813 | * BufferIndex Index of the buffer. 1814 | * Flags Flags to set for the buffer. 1815 | * 1816 | * Return value 1817 | * >= 0 O.K. 1818 | * < 0 Error 1819 | */ 1820 | int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { 1821 | int r; 1822 | volatile SEGGER_RTT_CB* pRTTCB; 1823 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1824 | 1825 | INIT(); 1826 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1827 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1828 | SEGGER_RTT_LOCK(); 1829 | pUp = &pRTTCB->aUp[BufferIndex]; 1830 | pUp->Flags = Flags; 1831 | SEGGER_RTT_UNLOCK(); 1832 | r = 0; 1833 | } else { 1834 | r = -1; 1835 | } 1836 | return r; 1837 | } 1838 | 1839 | /********************************************************************* 1840 | * 1841 | * SEGGER_RTT_SetFlagsDownBuffer 1842 | * 1843 | * Function description 1844 | * Run-time configuration of specific Down-buffer flags (T->H). 1845 | * Buffer to be configured is specified by index. 1846 | * 1847 | * Parameters 1848 | * BufferIndex Index of the buffer to renamed. 1849 | * Flags Flags to set for the buffer. 1850 | * 1851 | * Return value 1852 | * >= 0 O.K. 1853 | * < 0 Error 1854 | */ 1855 | int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { 1856 | int r; 1857 | volatile SEGGER_RTT_CB* pRTTCB; 1858 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1859 | 1860 | INIT(); 1861 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1862 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1863 | SEGGER_RTT_LOCK(); 1864 | pDown = &pRTTCB->aDown[BufferIndex]; 1865 | pDown->Flags = Flags; 1866 | SEGGER_RTT_UNLOCK(); 1867 | r = 0; 1868 | } else { 1869 | r = -1; 1870 | } 1871 | return r; 1872 | } 1873 | 1874 | /********************************************************************* 1875 | * 1876 | * SEGGER_RTT_Init 1877 | * 1878 | * Function description 1879 | * Initializes the RTT Control Block. 1880 | * Should be used in RAM targets, at start of the application. 1881 | * 1882 | */ 1883 | void SEGGER_RTT_Init (void) { 1884 | _DoInit(); 1885 | } 1886 | 1887 | /********************************************************************* 1888 | * 1889 | * SEGGER_RTT_SetTerminal 1890 | * 1891 | * Function description 1892 | * Sets the terminal to be used for output on channel 0. 1893 | * 1894 | * Parameters 1895 | * TerminalId Index of the terminal. 1896 | * 1897 | * Return value 1898 | * >= 0 O.K. 1899 | * < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) 1900 | * 1901 | * Notes 1902 | * (1) Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed 1903 | */ 1904 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { 1905 | unsigned char ac[2]; 1906 | SEGGER_RTT_BUFFER_UP* pRing; 1907 | unsigned Avail; 1908 | int r; 1909 | 1910 | INIT(); 1911 | r = 0; 1912 | ac[0] = 0xFFu; 1913 | if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels 1914 | ac[1] = _aTerminalId[TerminalId]; 1915 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1916 | SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing 1917 | if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1918 | _ActiveTerminal = TerminalId; 1919 | _WriteBlocking(pRing, (const char*)ac, 2u); 1920 | } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes 1921 | Avail = _GetAvailWriteSpace(pRing); 1922 | if (Avail >= 2) { 1923 | _ActiveTerminal = TerminalId; // Only change active terminal in case of success 1924 | _WriteNoCheck(pRing, (const char*)ac, 2u); 1925 | } else { 1926 | r = -1; 1927 | } 1928 | } 1929 | SEGGER_RTT_UNLOCK(); 1930 | } else { 1931 | r = -1; 1932 | } 1933 | return r; 1934 | } 1935 | 1936 | /********************************************************************* 1937 | * 1938 | * SEGGER_RTT_TerminalOut 1939 | * 1940 | * Function description 1941 | * Writes a string to the given terminal 1942 | * without changing the terminal for channel 0. 1943 | * 1944 | * Parameters 1945 | * TerminalId Index of the terminal. 1946 | * s String to be printed on the terminal. 1947 | * 1948 | * Return value 1949 | * >= 0 - Number of bytes written. 1950 | * < 0 - Error. 1951 | * 1952 | */ 1953 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { 1954 | int Status; 1955 | unsigned FragLen; 1956 | unsigned Avail; 1957 | SEGGER_RTT_BUFFER_UP* pRing; 1958 | // 1959 | INIT(); 1960 | // 1961 | // Validate terminal ID. 1962 | // 1963 | if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels 1964 | // 1965 | // Get "to-host" ring buffer. 1966 | // 1967 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1968 | // 1969 | // Need to be able to change terminal, write data, change back. 1970 | // Compute the fixed and variable sizes. 1971 | // 1972 | FragLen = STRLEN(s); 1973 | // 1974 | // How we output depends upon the mode... 1975 | // 1976 | SEGGER_RTT_LOCK(); 1977 | Avail = _GetAvailWriteSpace(pRing); 1978 | switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { 1979 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1980 | // 1981 | // If we are in skip mode and there is no space for the whole 1982 | // of this output, don't bother switching terminals at all. 1983 | // 1984 | if (Avail < (FragLen + 4u)) { 1985 | Status = 0; 1986 | } else { 1987 | _PostTerminalSwitch(pRing, TerminalId); 1988 | Status = (int)_WriteBlocking(pRing, s, FragLen); 1989 | _PostTerminalSwitch(pRing, _ActiveTerminal); 1990 | } 1991 | break; 1992 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1993 | // 1994 | // If we are in trim mode and there is not enough space for everything, 1995 | // trim the output but always include the terminal switch. If no room 1996 | // for terminal switch, skip that totally. 1997 | // 1998 | if (Avail < 4u) { 1999 | Status = -1; 2000 | } else { 2001 | _PostTerminalSwitch(pRing, TerminalId); 2002 | Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); 2003 | _PostTerminalSwitch(pRing, _ActiveTerminal); 2004 | } 2005 | break; 2006 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 2007 | // 2008 | // If we are in blocking mode, output everything. 2009 | // 2010 | _PostTerminalSwitch(pRing, TerminalId); 2011 | Status = (int)_WriteBlocking(pRing, s, FragLen); 2012 | _PostTerminalSwitch(pRing, _ActiveTerminal); 2013 | break; 2014 | default: 2015 | Status = -1; 2016 | break; 2017 | } 2018 | // 2019 | // Finish up. 2020 | // 2021 | SEGGER_RTT_UNLOCK(); 2022 | } else { 2023 | Status = -1; 2024 | } 2025 | return Status; 2026 | } 2027 | 2028 | /********************************************************************* 2029 | * 2030 | * SEGGER_RTT_GetAvailWriteSpace 2031 | * 2032 | * Function description 2033 | * Returns the number of bytes available in the ring buffer. 2034 | * 2035 | * Parameters 2036 | * BufferIndex Index of the up buffer. 2037 | * 2038 | * Return value 2039 | * Number of bytes that are free in the selected up buffer. 2040 | */ 2041 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex) { 2042 | SEGGER_RTT_BUFFER_UP* pRing; 2043 | 2044 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 2045 | return _GetAvailWriteSpace(pRing); 2046 | } 2047 | 2048 | 2049 | /********************************************************************* 2050 | * 2051 | * SEGGER_RTT_GetBytesInBuffer() 2052 | * 2053 | * Function description 2054 | * Returns the number of bytes currently used in the up buffer. 2055 | * 2056 | * Parameters 2057 | * BufferIndex Index of the up buffer. 2058 | * 2059 | * Return value 2060 | * Number of bytes that are used in the buffer. 2061 | */ 2062 | unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { 2063 | unsigned RdOff; 2064 | unsigned WrOff; 2065 | unsigned r; 2066 | volatile SEGGER_RTT_CB* pRTTCB; 2067 | // 2068 | // Avoid warnings regarding volatile access order. It's not a problem 2069 | // in this case, but dampen compiler enthusiasm. 2070 | // 2071 | pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 2072 | RdOff = pRTTCB->aUp[BufferIndex].RdOff; 2073 | WrOff = pRTTCB->aUp[BufferIndex].WrOff; 2074 | if (RdOff <= WrOff) { 2075 | r = WrOff - RdOff; 2076 | } else { 2077 | r = pRTTCB->aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); 2078 | } 2079 | return r; 2080 | } 2081 | 2082 | /*************************** End of file ****************************/ 2083 | -------------------------------------------------------------------------------- /RTT/SEGGER_RTT.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2021 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | * * 45 | * RTT version: 7.20a * 46 | * * 47 | ********************************************************************** 48 | 49 | ---------------------------END-OF-HEADER------------------------------ 50 | File : SEGGER_RTT.h 51 | Purpose : Implementation of SEGGER real-time transfer which allows 52 | real-time communication on targets which support debugger 53 | memory accesses while the CPU is running. 54 | Revision: $Rev: 20869 $ 55 | ---------------------------------------------------------------------- 56 | */ 57 | 58 | #ifndef SEGGER_RTT_H 59 | #define SEGGER_RTT_H 60 | 61 | #include "SEGGER_RTT_Conf.h" 62 | 63 | /********************************************************************* 64 | * 65 | * Defines, defaults 66 | * 67 | ********************************************************************** 68 | */ 69 | #ifndef RTT_USE_ASM 70 | #if (defined __SES_ARM) // SEGGER Embedded Studio 71 | #define _CC_HAS_RTT_ASM_SUPPORT 1 72 | #elif (defined __CROSSWORKS_ARM) // Rowley Crossworks 73 | #define _CC_HAS_RTT_ASM_SUPPORT 1 74 | #elif (defined __ARMCC_VERSION) // ARM compiler 75 | #if (__ARMCC_VERSION >= 6000000) // ARM compiler V6.0 and later is clang based 76 | #define _CC_HAS_RTT_ASM_SUPPORT 1 77 | #else 78 | #define _CC_HAS_RTT_ASM_SUPPORT 0 79 | #endif 80 | #elif (defined __GNUC__) // GCC 81 | #define _CC_HAS_RTT_ASM_SUPPORT 1 82 | #elif (defined __clang__) // Clang compiler 83 | #define _CC_HAS_RTT_ASM_SUPPORT 1 84 | #elif ((defined __IASMARM__) || (defined __ICCARM__)) // IAR assembler/compiler 85 | #define _CC_HAS_RTT_ASM_SUPPORT 1 86 | #else 87 | #define _CC_HAS_RTT_ASM_SUPPORT 0 88 | #endif 89 | #if ((defined __IASMARM__) || (defined __ICCARM__)) // IAR assembler/compiler 90 | // 91 | // IAR assembler / compiler 92 | // 93 | #if (__VER__ < 6300000) 94 | #define VOLATILE 95 | #else 96 | #define VOLATILE volatile 97 | #endif 98 | #if (defined __ARM7M__) // Needed for old versions that do not know the define yet 99 | #if (__CORE__ == __ARM7M__) // Cortex-M3 100 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 101 | #endif 102 | #endif 103 | #if (defined __ARM7EM__) // Needed for old versions that do not know the define yet 104 | #if (__CORE__ == __ARM7EM__) // Cortex-M4/M7 105 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 106 | #define _CORE_NEEDS_DMB 1 107 | #define RTT__DMB() asm VOLATILE ("DMB"); 108 | #endif 109 | #endif 110 | #if (defined __ARM8M_BASELINE__) // Needed for old versions that do not know the define yet 111 | #if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23 112 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 113 | #define _CORE_NEEDS_DMB 1 114 | #define RTT__DMB() asm VOLATILE ("DMB"); 115 | #endif 116 | #endif 117 | #if (defined __ARM8M_MAINLINE__) // Needed for old versions that do not know the define yet 118 | #if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33 119 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 120 | #define _CORE_NEEDS_DMB 1 121 | #define RTT__DMB() asm VOLATILE ("DMB"); 122 | #endif 123 | #endif 124 | #else 125 | // 126 | // GCC / Clang 127 | // 128 | #if (defined __ARM_ARCH_7M__) // Cortex-M3 129 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 130 | #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 131 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 132 | #define _CORE_NEEDS_DMB 1 133 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 134 | #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 135 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 136 | #define _CORE_NEEDS_DMB 1 137 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 138 | #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 139 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 140 | #define _CORE_NEEDS_DMB 1 141 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 142 | #else 143 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 144 | #endif 145 | #endif 146 | // 147 | // If IDE and core support the ASM version, enable ASM version by default 148 | // 149 | #ifndef _CORE_HAS_RTT_ASM_SUPPORT 150 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores 151 | #endif 152 | #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) 153 | #define RTT_USE_ASM (1) 154 | #else 155 | #define RTT_USE_ASM (0) 156 | #endif 157 | #endif 158 | 159 | // 160 | // We need to know if a DMB is needed to make sure that on Cortex-M7 etc. 161 | // the order of accesses to the ring buffers is guaranteed 162 | // Needed for: Cortex-M7, Cortex-M23, Cortex-M33 163 | // 164 | #ifndef _CORE_NEEDS_DMB 165 | #define _CORE_NEEDS_DMB 0 166 | #endif 167 | 168 | #ifndef RTT__DMB 169 | #if _CORE_NEEDS_DMB 170 | #error "Don't know how to place inline assembly for DMB" 171 | #else 172 | #define RTT__DMB() 173 | #endif 174 | #endif 175 | 176 | #ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE 177 | #define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here 178 | #endif 179 | 180 | #ifndef SEGGER_RTT_UNCACHED_OFF 181 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 182 | #error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 183 | #else 184 | #define SEGGER_RTT_UNCACHED_OFF (0) 185 | #endif 186 | #endif 187 | #if RTT_USE_ASM 188 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 189 | #error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 190 | #endif 191 | #endif 192 | 193 | #ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file 194 | #include 195 | #include 196 | 197 | /********************************************************************* 198 | * 199 | * Defines, fixed 200 | * 201 | ********************************************************************** 202 | */ 203 | 204 | // 205 | // Determine how much we must pad the control block to make it a multiple of a cache line in size 206 | // Assuming: U8 = 1B 207 | // U16 = 2B 208 | // U32 = 4B 209 | // U8/U16/U32* = 4B 210 | // 211 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache 212 | #define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE) 213 | #else 214 | #define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes) 215 | #endif 216 | #define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24)) 217 | #define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE) 218 | 219 | /********************************************************************* 220 | * 221 | * Types 222 | * 223 | ********************************************************************** 224 | */ 225 | 226 | // 227 | // Description for a circular buffer (also called "ring buffer") 228 | // which is used as up-buffer (T->H) 229 | // 230 | typedef struct { 231 | const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" 232 | char* pBuffer; // Pointer to start of buffer 233 | unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. 234 | unsigned WrOff; // Position of next item to be written by either target. 235 | volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. 236 | unsigned Flags; // Contains configuration flags 237 | } SEGGER_RTT_BUFFER_UP; 238 | 239 | // 240 | // Description for a circular buffer (also called "ring buffer") 241 | // which is used as down-buffer (H->T) 242 | // 243 | typedef struct { 244 | const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" 245 | char* pBuffer; // Pointer to start of buffer 246 | unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. 247 | volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. 248 | unsigned RdOff; // Position of next item to be read by target (down-buffer). 249 | unsigned Flags; // Contains configuration flags 250 | } SEGGER_RTT_BUFFER_DOWN; 251 | 252 | // 253 | // RTT control block which describes the number of buffers available 254 | // as well as the configuration for each buffer 255 | // 256 | // 257 | typedef struct { 258 | char acID[16]; // Initialized to "SEGGER RTT" 259 | int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) 260 | int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) 261 | SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host 262 | SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target 263 | #if SEGGER_RTT__CB_PADDING 264 | unsigned char aDummy[SEGGER_RTT__CB_PADDING]; 265 | #endif 266 | } SEGGER_RTT_CB; 267 | 268 | /********************************************************************* 269 | * 270 | * Global data 271 | * 272 | ********************************************************************** 273 | */ 274 | extern SEGGER_RTT_CB _SEGGER_RTT; 275 | 276 | /********************************************************************* 277 | * 278 | * RTT API functions 279 | * 280 | ********************************************************************** 281 | */ 282 | #ifdef __cplusplus 283 | extern "C" { 284 | #endif 285 | int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 286 | int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 287 | int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 288 | int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 289 | int SEGGER_RTT_GetKey (void); 290 | unsigned SEGGER_RTT_HasData (unsigned BufferIndex); 291 | int SEGGER_RTT_HasKey (void); 292 | unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); 293 | void SEGGER_RTT_Init (void); 294 | unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 295 | unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 296 | int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); 297 | int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); 298 | int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); 299 | int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); 300 | int SEGGER_RTT_WaitKey (void); 301 | unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 302 | unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 303 | unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 304 | unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 305 | unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); 306 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 307 | unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); 308 | unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); 309 | unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); 310 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); 311 | unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); 312 | // 313 | // Function macro for performance optimization 314 | // 315 | #define SEGGER_RTT_HASDATA(n) (((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) 316 | 317 | #if RTT_USE_ASM 318 | #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock 319 | #endif 320 | 321 | /********************************************************************* 322 | * 323 | * RTT transfer functions to send RTT data via other channels. 324 | * 325 | ********************************************************************** 326 | */ 327 | unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 328 | unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 329 | unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 330 | unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 331 | 332 | #define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 333 | 334 | /********************************************************************* 335 | * 336 | * RTT "Terminal" API functions 337 | * 338 | ********************************************************************** 339 | */ 340 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId); 341 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); 342 | 343 | /********************************************************************* 344 | * 345 | * RTT printf functions (require SEGGER_RTT_printf.c) 346 | * 347 | ********************************************************************** 348 | */ 349 | int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); 350 | int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); 351 | 352 | #ifdef __cplusplus 353 | } 354 | #endif 355 | 356 | #endif // ifndef(SEGGER_RTT_ASM) 357 | 358 | /********************************************************************* 359 | * 360 | * Defines 361 | * 362 | ********************************************************************** 363 | */ 364 | 365 | // 366 | // Operating modes. Define behavior if buffer is full (not enough space for entire message) 367 | // 368 | #define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) 369 | #define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. 370 | #define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. 371 | #define SEGGER_RTT_MODE_MASK (3) 372 | 373 | // 374 | // Control sequences, based on ANSI. 375 | // Can be used to control color, and clear the screen 376 | // 377 | #define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors 378 | #define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left 379 | 380 | #define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" 381 | #define RTT_CTRL_TEXT_RED "\x1B[2;31m" 382 | #define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" 383 | #define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" 384 | #define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" 385 | #define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" 386 | #define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" 387 | #define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" 388 | 389 | #define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" 390 | #define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" 391 | #define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" 392 | #define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" 393 | #define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" 394 | #define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" 395 | #define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" 396 | #define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" 397 | 398 | #define RTT_CTRL_BG_BLACK "\x1B[24;40m" 399 | #define RTT_CTRL_BG_RED "\x1B[24;41m" 400 | #define RTT_CTRL_BG_GREEN "\x1B[24;42m" 401 | #define RTT_CTRL_BG_YELLOW "\x1B[24;43m" 402 | #define RTT_CTRL_BG_BLUE "\x1B[24;44m" 403 | #define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" 404 | #define RTT_CTRL_BG_CYAN "\x1B[24;46m" 405 | #define RTT_CTRL_BG_WHITE "\x1B[24;47m" 406 | 407 | #define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" 408 | #define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" 409 | #define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" 410 | #define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" 411 | #define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" 412 | #define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" 413 | #define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" 414 | #define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" 415 | 416 | 417 | #endif 418 | 419 | /*************************** End of file ****************************/ 420 | -------------------------------------------------------------------------------- /RTT/SEGGER_RTT_ASM_ARMv7M.S: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * (c) SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | * www.segger.com * 5 | ********************************************************************** 6 | 7 | -------------------------- END-OF-HEADER ----------------------------- 8 | 9 | File : SEGGER_RTT_ASM_ARMv7M.S 10 | Purpose : Assembler implementation of RTT functions for ARMv7M 11 | 12 | Additional information: 13 | This module is written to be assembler-independent and works with 14 | GCC and clang (Embedded Studio) and IAR. 15 | */ 16 | 17 | #define SEGGER_RTT_ASM // Used to control processed input from header file 18 | #include "SEGGER_RTT.h" 19 | 20 | /********************************************************************* 21 | * 22 | * Defines, fixed 23 | * 24 | ********************************************************************** 25 | */ 26 | 27 | #define _CCIAR 0 28 | #define _CCCLANG 1 29 | 30 | #if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__) 31 | #define _CC_TYPE _CCCLANG 32 | #define _PUB_SYM .global 33 | #define _EXT_SYM .extern 34 | #define _END .end 35 | #define _WEAK .weak 36 | #define _THUMB_FUNC .thumb_func 37 | #define _THUMB_CODE .code 16 38 | #define _WORD .word 39 | #define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax" 40 | #define _ALIGN(Exp) .align Exp 41 | #define _PLACE_LITS .ltorg 42 | #define _DATA_SECT_START 43 | #define _C_STARTUP _start 44 | #define _STACK_END __stack_end__ 45 | #define _RAMFUNC 46 | // 47 | // .text => Link to flash 48 | // .fast => Link to RAM 49 | // OtherSect => Usually link to RAM 50 | // Alignment is 2^x 51 | // 52 | #elif defined (__IASMARM__) 53 | #define _CC_TYPE _CCIAR 54 | #define _PUB_SYM PUBLIC 55 | #define _EXT_SYM EXTERN 56 | #define _END END 57 | #define _WEAK _WEAK 58 | #define _THUMB_FUNC 59 | #define _THUMB_CODE THUMB 60 | #define _WORD DCD 61 | #define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp) 62 | #define _ALIGN(Exp) alignrom Exp 63 | #define _PLACE_LITS 64 | #define _DATA_SECT_START DATA 65 | #define _C_STARTUP __iar_program_start 66 | #define _STACK_END sfe(CSTACK) 67 | #define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR 68 | // 69 | // .text => Link to flash 70 | // .textrw => Link to RAM 71 | // OtherSect => Usually link to RAM 72 | // NOROOT => Allows linker to throw away the function, if not referenced 73 | // Alignment is 2^x 74 | // 75 | #endif 76 | 77 | #if (_CC_TYPE == _CCIAR) 78 | NAME SEGGER_RTT_ASM_ARMv7M 79 | #else 80 | .syntax unified 81 | #endif 82 | 83 | #if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) 84 | #define SHT_PROGBITS 0x1 85 | 86 | /********************************************************************* 87 | * 88 | * Public / external symbols 89 | * 90 | ********************************************************************** 91 | */ 92 | 93 | _EXT_SYM __aeabi_memcpy 94 | _EXT_SYM __aeabi_memcpy4 95 | _EXT_SYM _SEGGER_RTT 96 | 97 | _PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock 98 | 99 | /********************************************************************* 100 | * 101 | * SEGGER_RTT_WriteSkipNoLock 102 | * 103 | * Function description 104 | * Stores a specified number of characters in SEGGER RTT 105 | * control block which is then read by the host. 106 | * SEGGER_RTT_WriteSkipNoLock does not lock the application and 107 | * skips all data, if the data does not fit into the buffer. 108 | * 109 | * Parameters 110 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 111 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 112 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 113 | * MUST be > 0!!! 114 | * This is done for performance reasons, so no initial check has do be done. 115 | * 116 | * Return value 117 | * 1: Data has been copied 118 | * 0: No space, data has not been copied 119 | * 120 | * Notes 121 | * (1) If there is not enough space in the "Up"-buffer, all data is dropped. 122 | * (2) For performance reasons this function does not call Init() 123 | * and may only be called after RTT has been initialized. 124 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 125 | */ 126 | _SECTION(.text, CODE, 2) 127 | _ALIGN(2) 128 | _THUMB_FUNC 129 | SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) { 130 | // 131 | // Cases: 132 | // 1) RdOff <= WrOff => Space until wrap-around is sufficient 133 | // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) 134 | // 3) RdOff < WrOff => No space in buf 135 | // 4) RdOff > WrOff => Space is sufficient 136 | // 5) RdOff > WrOff => No space in buf 137 | // 138 | // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough 139 | // 140 | // Register usage: 141 | // R0 Temporary needed as RdOff, register later on 142 | // R1 pData 143 | // R2 144 | // R3 register. Hold free for subroutine calls 145 | // R4 146 | // R5 pRing->pBuffer 147 | // R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN) 148 | // R7 WrOff 149 | // 150 | PUSH {R4-R7} 151 | ADD R3,R0,R0, LSL #+1 152 | LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex]; 153 | ADD R0,R0,R3, LSL #+3 154 | ADD R6,R0,#+24 155 | LDR R0,[R6, #+16] // RdOff = pRing->RdOff; 156 | LDR R7,[R6, #+12] // WrOff = pRing->WrOff; 157 | LDR R5,[R6, #+4] // pRing->pBuffer 158 | CMP R7,R0 159 | BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3) 160 | // 161 | // Handling for case 1, later on identical to case 4 162 | // 163 | LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) 164 | SUBS R4,R3,R7 // (Used in case we jump into case 2 afterwards) 165 | SUBS R3,R4,#+1 // 166 | CMP R3,R2 167 | BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)? 168 | _Case4: 169 | ADDS R5,R7,R5 // pBuffer += WrOff 170 | ADDS R0,R2,R7 // v = WrOff + NumBytes 171 | // 172 | // 2x unrolling for the copy loop that is used most of the time 173 | // This is a special optimization for small SystemView packets and makes them even faster 174 | // 175 | _ALIGN(2) 176 | _LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes); 177 | LDRB R3,[R1], #+1 178 | STRB R3,[R5], #+1 // *pDest++ = *pSrc++ 179 | SUBS R2,R2,#+1 180 | BEQ _CSDone 181 | LDRB R3,[R1], #+1 182 | STRB R3,[R5], #+1 // *pDest++ = *pSrc++ 183 | SUBS R2,R2,#+1 184 | BNE _LoopCopyStraight 185 | _CSDone: 186 | #if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here 187 | DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the in the struct 188 | #endif 189 | STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes; 190 | MOVS R0,#+1 191 | POP {R4-R7} 192 | BX LR // Return 1 193 | _CheckCase2: 194 | ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around 195 | CMP R0,R2 196 | BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit) 197 | // 198 | // Handling for case 2 199 | // 200 | ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value 201 | SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer) 202 | _LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk 203 | LDRB R3,[R1], #+1 204 | STRB R3,[R0], #+1 // *pDest++ = *pSrc++ 205 | SUBS R4,R4,#+1 206 | BNE _LoopCopyBeforeWrapAround 207 | // 208 | // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used 209 | // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element 210 | // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks 211 | // Therefore, check if 2nd memcpy is necessary at all 212 | // 213 | ADDS R4,R2,#+0 // Save (needed as counter in loop but must be written to after the loop). Also use this inst to update the flags to skip 2nd loop if possible 214 | BEQ.N _No2ChunkNeeded // if (NumBytes) { 215 | _LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes); 216 | LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop 217 | STRB R3,[R5], #+1 // *pDest++ = *pSrc++ 218 | SUBS R2,R2,#+1 219 | BNE _LoopCopyAfterWrapAround 220 | _No2ChunkNeeded: 221 | #if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here 222 | DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the in the struct 223 | #endif 224 | STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer 225 | MOVS R0,#+1 226 | POP {R4-R7} 227 | BX LR // Return 1 228 | _CheckCase4: 229 | SUBS R0,R0,R7 230 | SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u; 231 | CMP R0,R2 232 | BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit) 233 | _Case3: 234 | MOVS R0,#+0 235 | POP {R4-R7} 236 | BX LR // Return 0 237 | _PLACE_LITS 238 | 239 | #endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) 240 | _END 241 | 242 | /*************************** End of file ****************************/ 243 | -------------------------------------------------------------------------------- /RTT/SEGGER_RTT_Conf.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2021 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | * * 45 | * RTT version: 7.20a * 46 | * * 47 | ********************************************************************** 48 | 49 | ---------------------------END-OF-HEADER------------------------------ 50 | File : SEGGER_RTT_Conf.h 51 | Purpose : Implementation of SEGGER real-time transfer (RTT) which 52 | allows real-time communication on targets which support 53 | debugger memory accesses while the CPU is running. 54 | Revision: $Rev: 21386 $ 55 | 56 | */ 57 | 58 | #ifndef SEGGER_RTT_CONF_H 59 | #define SEGGER_RTT_CONF_H 60 | 61 | #ifdef __IAR_SYSTEMS_ICC__ 62 | #include 63 | #endif 64 | 65 | #include "rtconfig.h" 66 | 67 | /********************************************************************* 68 | * 69 | * Defines, configurable 70 | * 71 | ********************************************************************** 72 | */ 73 | 74 | // 75 | // Take in and set to correct values for Cortex-A systems with CPU cache 76 | // 77 | //#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system 78 | //#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached 79 | // 80 | // Most common case: 81 | // Up-channel 0: RTT 82 | // Up-channel 1: SystemView 83 | // 84 | #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 85 | #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) 86 | #endif 87 | // 88 | // Most common case: 89 | // Down-channel 0: RTT 90 | // Down-channel 1: SystemView 91 | // 92 | #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 93 | #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) 94 | #endif 95 | 96 | 97 | #ifndef BUFFER_SIZE_UP 98 | #define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) 99 | #endif 100 | 101 | #ifndef BUFFER_SIZE_DOWN 102 | #define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) 103 | #endif 104 | 105 | #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE 106 | #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) 107 | #endif 108 | 109 | #ifndef SEGGER_RTT_MODE_DEFAULT 110 | #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) 111 | #endif 112 | 113 | /********************************************************************* 114 | * 115 | * RTT memcpy configuration 116 | * 117 | * memcpy() is good for large amounts of data, 118 | * but the overhead is big for small amounts, which are usually stored via RTT. 119 | * With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. 120 | * 121 | * SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. 122 | * This is may be required with memory access restrictions, 123 | * such as on Cortex-A devices with MMU. 124 | */ 125 | #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP 126 | #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop 127 | #endif 128 | // 129 | // Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets 130 | // 131 | //#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) 132 | // #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) 133 | //#endif 134 | 135 | // 136 | // Target is not allowed to perform other RTT operations while string still has not been stored completely. 137 | // Otherwise we would probably end up with a mixed string in the buffer. 138 | // If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. 139 | // 140 | // SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. 141 | // Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. 142 | // When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. 143 | // (Higher priority = lower priority number) 144 | // Default value for embOS: 128u 145 | // Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) 146 | // In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC 147 | // or define SEGGER_RTT_LOCK() to completely disable interrupts. 148 | // 149 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 150 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) 151 | #endif 152 | 153 | /********************************************************************* 154 | * 155 | * RTT lock configuration for SEGGER Embedded Studio, 156 | * Rowley CrossStudio and GCC 157 | */ 158 | #if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32)) 159 | #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) 160 | #define SEGGER_RTT_LOCK() { \ 161 | unsigned int _SEGGER_RTT__LockState; \ 162 | __asm volatile ("mrs %0, primask \n\t" \ 163 | "movs r1, #1 \n\t" \ 164 | "msr primask, r1 \n\t" \ 165 | : "=r" (_SEGGER_RTT__LockState) \ 166 | : \ 167 | : "r1", "cc" \ 168 | ); 169 | 170 | #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ 171 | : \ 172 | : "r" (_SEGGER_RTT__LockState) \ 173 | : \ 174 | ); \ 175 | } 176 | #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) 177 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 178 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 179 | #endif 180 | #define SEGGER_RTT_LOCK() { \ 181 | unsigned int _SEGGER_RTT__LockState; \ 182 | __asm volatile ("mrs %0, basepri \n\t" \ 183 | "mov r1, %1 \n\t" \ 184 | "msr basepri, r1 \n\t" \ 185 | : "=r" (_SEGGER_RTT__LockState) \ 186 | : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ 187 | : "r1", "cc" \ 188 | ); 189 | 190 | #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ 191 | : \ 192 | : "r" (_SEGGER_RTT__LockState) \ 193 | : \ 194 | ); \ 195 | } 196 | 197 | #elif defined(__ARM_ARCH_7A__) 198 | #define SEGGER_RTT_LOCK() { \ 199 | unsigned int _SEGGER_RTT__LockState; \ 200 | __asm volatile ("mrs r1, CPSR \n\t" \ 201 | "mov %0, r1 \n\t" \ 202 | "orr r1, r1, #0xC0 \n\t" \ 203 | "msr CPSR_c, r1 \n\t" \ 204 | : "=r" (_SEGGER_RTT__LockState) \ 205 | : \ 206 | : "r1", "cc" \ 207 | ); 208 | 209 | #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ 210 | "mrs r1, CPSR \n\t" \ 211 | "bic r1, r1, #0xC0 \n\t" \ 212 | "and r0, r0, #0xC0 \n\t" \ 213 | "orr r1, r1, r0 \n\t" \ 214 | "msr CPSR_c, r1 \n\t" \ 215 | : \ 216 | : "r" (_SEGGER_RTT__LockState) \ 217 | : "r0", "r1", "cc" \ 218 | ); \ 219 | } 220 | #elif defined(__riscv) || defined(__riscv_xlen) 221 | #define SEGGER_RTT_LOCK() { \ 222 | unsigned int _SEGGER_RTT__LockState; \ 223 | __asm volatile ("csrr %0, mstatus \n\t" \ 224 | "csrci mstatus, 8 \n\t" \ 225 | "andi %0, %0, 8 \n\t" \ 226 | : "=r" (_SEGGER_RTT__LockState) \ 227 | : \ 228 | : \ 229 | ); 230 | 231 | #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \ 232 | "or %0, %0, a1 \n\t" \ 233 | "csrs mstatus, %0 \n\t" \ 234 | : \ 235 | : "r" (_SEGGER_RTT__LockState) \ 236 | : "a1" \ 237 | ); \ 238 | } 239 | #else 240 | #define SEGGER_RTT_LOCK() 241 | #define SEGGER_RTT_UNLOCK() 242 | #endif 243 | #endif 244 | 245 | /********************************************************************* 246 | * 247 | * RTT lock configuration for IAR EWARM 248 | */ 249 | #ifdef __ICCARM__ 250 | #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \ 251 | (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) 252 | #define SEGGER_RTT_LOCK() { \ 253 | unsigned int _SEGGER_RTT__LockState; \ 254 | _SEGGER_RTT__LockState = __get_PRIMASK(); \ 255 | __set_PRIMASK(1); 256 | 257 | #define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \ 258 | } 259 | #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \ 260 | (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \ 261 | (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \ 262 | (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) 263 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 264 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 265 | #endif 266 | #define SEGGER_RTT_LOCK() { \ 267 | unsigned int _SEGGER_RTT__LockState; \ 268 | _SEGGER_RTT__LockState = __get_BASEPRI(); \ 269 | __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); 270 | 271 | #define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \ 272 | } 273 | #elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \ 274 | (defined (__ARM7R__) && (__CORE__ == __ARM7R__)) 275 | #define SEGGER_RTT_LOCK() { \ 276 | unsigned int _SEGGER_RTT__LockState; \ 277 | __asm volatile ("mrs r1, CPSR \n\t" \ 278 | "mov %0, r1 \n\t" \ 279 | "orr r1, r1, #0xC0 \n\t" \ 280 | "msr CPSR_c, r1 \n\t" \ 281 | : "=r" (_SEGGER_RTT__LockState) \ 282 | : \ 283 | : "r1", "cc" \ 284 | ); 285 | 286 | #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ 287 | "mrs r1, CPSR \n\t" \ 288 | "bic r1, r1, #0xC0 \n\t" \ 289 | "and r0, r0, #0xC0 \n\t" \ 290 | "orr r1, r1, r0 \n\t" \ 291 | "msr CPSR_c, r1 \n\t" \ 292 | : \ 293 | : "r" (_SEGGER_RTT__LockState) \ 294 | : "r0", "r1", "cc" \ 295 | ); \ 296 | } 297 | #endif 298 | #endif 299 | 300 | /********************************************************************* 301 | * 302 | * RTT lock configuration for IAR RX 303 | */ 304 | #ifdef __ICCRX__ 305 | #define SEGGER_RTT_LOCK() { \ 306 | unsigned long _SEGGER_RTT__LockState; \ 307 | _SEGGER_RTT__LockState = __get_interrupt_state(); \ 308 | __disable_interrupt(); 309 | 310 | #define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \ 311 | } 312 | #endif 313 | 314 | /********************************************************************* 315 | * 316 | * RTT lock configuration for IAR RL78 317 | */ 318 | #ifdef __ICCRL78__ 319 | #define SEGGER_RTT_LOCK() { \ 320 | __istate_t _SEGGER_RTT__LockState; \ 321 | _SEGGER_RTT__LockState = __get_interrupt_state(); \ 322 | __disable_interrupt(); 323 | 324 | #define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \ 325 | } 326 | #endif 327 | 328 | /********************************************************************* 329 | * 330 | * RTT lock configuration for KEIL ARM 331 | */ 332 | #ifdef __CC_ARM 333 | #if (defined __TARGET_ARCH_6S_M) 334 | #define SEGGER_RTT_LOCK() { \ 335 | unsigned int _SEGGER_RTT__LockState; \ 336 | register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \ 337 | _SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \ 338 | _SEGGER_RTT__PRIMASK = 1u; \ 339 | __schedule_barrier(); 340 | 341 | #define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \ 342 | __schedule_barrier(); \ 343 | } 344 | #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) 345 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 346 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 347 | #endif 348 | #define SEGGER_RTT_LOCK() { \ 349 | unsigned int _SEGGER_RTT__LockState; \ 350 | register unsigned char BASEPRI __asm( "basepri"); \ 351 | _SEGGER_RTT__LockState = BASEPRI; \ 352 | BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ 353 | __schedule_barrier(); 354 | 355 | #define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \ 356 | __schedule_barrier(); \ 357 | } 358 | #endif 359 | #endif 360 | 361 | /********************************************************************* 362 | * 363 | * RTT lock configuration for TI ARM 364 | */ 365 | #ifdef __TI_ARM__ 366 | #if defined (__TI_ARM_V6M0__) 367 | #define SEGGER_RTT_LOCK() { \ 368 | unsigned int _SEGGER_RTT__LockState; \ 369 | _SEGGER_RTT__LockState = __get_PRIMASK(); \ 370 | __set_PRIMASK(1); 371 | 372 | #define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \ 373 | } 374 | #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) 375 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 376 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 377 | #endif 378 | #define SEGGER_RTT_LOCK() { \ 379 | unsigned int _SEGGER_RTT__LockState; \ 380 | _SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); 381 | 382 | #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \ 383 | } 384 | #endif 385 | #endif 386 | 387 | /********************************************************************* 388 | * 389 | * RTT lock configuration for CCRX 390 | */ 391 | #ifdef __RX 392 | #include 393 | #define SEGGER_RTT_LOCK() { \ 394 | unsigned long _SEGGER_RTT__LockState; \ 395 | _SEGGER_RTT__LockState = get_psw() & 0x010000; \ 396 | clrpsw_i(); 397 | 398 | #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \ 399 | } 400 | #endif 401 | 402 | /********************************************************************* 403 | * 404 | * RTT lock configuration for embOS Simulation on Windows 405 | * (Can also be used for generic RTT locking with embOS) 406 | */ 407 | #if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS) 408 | 409 | void OS_SIM_EnterCriticalSection(void); 410 | void OS_SIM_LeaveCriticalSection(void); 411 | 412 | #define SEGGER_RTT_LOCK() { \ 413 | OS_SIM_EnterCriticalSection(); 414 | 415 | #define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \ 416 | } 417 | #endif 418 | 419 | /********************************************************************* 420 | * 421 | * RTT lock configuration fallback 422 | */ 423 | #ifndef SEGGER_RTT_LOCK 424 | #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) 425 | #endif 426 | 427 | #ifndef SEGGER_RTT_UNLOCK 428 | #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) 429 | #endif 430 | 431 | #endif 432 | /*************************** End of file ****************************/ 433 | -------------------------------------------------------------------------------- /RTT/SEGGER_RTT_printf.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2021 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | * * 45 | * RTT version: 7.20a * 46 | * * 47 | ********************************************************************** 48 | 49 | ---------------------------END-OF-HEADER------------------------------ 50 | File : SEGGER_RTT_printf.c 51 | Purpose : Replacement for printf to write formatted data via RTT 52 | Revision: $Rev: 17697 $ 53 | ---------------------------------------------------------------------- 54 | */ 55 | #include "SEGGER_RTT.h" 56 | #include "SEGGER_RTT_Conf.h" 57 | 58 | /********************************************************************* 59 | * 60 | * Defines, configurable 61 | * 62 | ********************************************************************** 63 | */ 64 | 65 | #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE 66 | #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) 67 | #endif 68 | 69 | #include 70 | #include 71 | 72 | 73 | #define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) 74 | #define FORMAT_FLAG_PAD_ZERO (1u << 1) 75 | #define FORMAT_FLAG_PRINT_SIGN (1u << 2) 76 | #define FORMAT_FLAG_ALTERNATE (1u << 3) 77 | 78 | /********************************************************************* 79 | * 80 | * Types 81 | * 82 | ********************************************************************** 83 | */ 84 | 85 | typedef struct { 86 | char* pBuffer; 87 | unsigned BufferSize; 88 | unsigned Cnt; 89 | 90 | int ReturnValue; 91 | 92 | unsigned RTTBufferIndex; 93 | } SEGGER_RTT_PRINTF_DESC; 94 | 95 | /********************************************************************* 96 | * 97 | * Function prototypes 98 | * 99 | ********************************************************************** 100 | */ 101 | 102 | /********************************************************************* 103 | * 104 | * Static code 105 | * 106 | ********************************************************************** 107 | */ 108 | /********************************************************************* 109 | * 110 | * _StoreChar 111 | */ 112 | static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { 113 | unsigned Cnt; 114 | 115 | Cnt = p->Cnt; 116 | if ((Cnt + 1u) <= p->BufferSize) { 117 | *(p->pBuffer + Cnt) = c; 118 | p->Cnt = Cnt + 1u; 119 | p->ReturnValue++; 120 | } 121 | // 122 | // Write part of string, when the buffer is full 123 | // 124 | if (p->Cnt == p->BufferSize) { 125 | if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { 126 | p->ReturnValue = -1; 127 | } else { 128 | p->Cnt = 0u; 129 | } 130 | } 131 | } 132 | 133 | /********************************************************************* 134 | * 135 | * _PrintUnsigned 136 | */ 137 | static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 138 | static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 139 | unsigned Div; 140 | unsigned Digit; 141 | unsigned Number; 142 | unsigned Width; 143 | char c; 144 | 145 | Number = v; 146 | Digit = 1u; 147 | // 148 | // Get actual field width 149 | // 150 | Width = 1u; 151 | while (Number >= Base) { 152 | Number = (Number / Base); 153 | Width++; 154 | } 155 | if (NumDigits > Width) { 156 | Width = NumDigits; 157 | } 158 | // 159 | // Print leading chars if necessary 160 | // 161 | if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { 162 | if (FieldWidth != 0u) { 163 | if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { 164 | c = '0'; 165 | } else { 166 | c = ' '; 167 | } 168 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 169 | FieldWidth--; 170 | _StoreChar(pBufferDesc, c); 171 | if (pBufferDesc->ReturnValue < 0) { 172 | break; 173 | } 174 | } 175 | } 176 | } 177 | if (pBufferDesc->ReturnValue >= 0) { 178 | // 179 | // Compute Digit. 180 | // Loop until Digit has the value of the highest digit required. 181 | // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. 182 | // 183 | while (1) { 184 | if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) 185 | NumDigits--; 186 | } else { 187 | Div = v / Digit; 188 | if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done 189 | break; 190 | } 191 | } 192 | Digit *= Base; 193 | } 194 | // 195 | // Output digits 196 | // 197 | do { 198 | Div = v / Digit; 199 | v -= Div * Digit; 200 | _StoreChar(pBufferDesc, _aV2C[Div]); 201 | if (pBufferDesc->ReturnValue < 0) { 202 | break; 203 | } 204 | Digit /= Base; 205 | } while (Digit); 206 | // 207 | // Print trailing spaces if necessary 208 | // 209 | if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { 210 | if (FieldWidth != 0u) { 211 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 212 | FieldWidth--; 213 | _StoreChar(pBufferDesc, ' '); 214 | if (pBufferDesc->ReturnValue < 0) { 215 | break; 216 | } 217 | } 218 | } 219 | } 220 | } 221 | } 222 | 223 | /********************************************************************* 224 | * 225 | * _PrintInt 226 | */ 227 | static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 228 | unsigned Width; 229 | int Number; 230 | 231 | Number = (v < 0) ? -v : v; 232 | 233 | // 234 | // Get actual field width 235 | // 236 | Width = 1u; 237 | while (Number >= (int)Base) { 238 | Number = (Number / (int)Base); 239 | Width++; 240 | } 241 | if (NumDigits > Width) { 242 | Width = NumDigits; 243 | } 244 | if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { 245 | FieldWidth--; 246 | } 247 | 248 | // 249 | // Print leading spaces if necessary 250 | // 251 | if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { 252 | if (FieldWidth != 0u) { 253 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 254 | FieldWidth--; 255 | _StoreChar(pBufferDesc, ' '); 256 | if (pBufferDesc->ReturnValue < 0) { 257 | break; 258 | } 259 | } 260 | } 261 | } 262 | // 263 | // Print sign if necessary 264 | // 265 | if (pBufferDesc->ReturnValue >= 0) { 266 | if (v < 0) { 267 | v = -v; 268 | _StoreChar(pBufferDesc, '-'); 269 | } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { 270 | _StoreChar(pBufferDesc, '+'); 271 | } else { 272 | 273 | } 274 | if (pBufferDesc->ReturnValue >= 0) { 275 | // 276 | // Print leading zeros if necessary 277 | // 278 | if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { 279 | if (FieldWidth != 0u) { 280 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 281 | FieldWidth--; 282 | _StoreChar(pBufferDesc, '0'); 283 | if (pBufferDesc->ReturnValue < 0) { 284 | break; 285 | } 286 | } 287 | } 288 | } 289 | if (pBufferDesc->ReturnValue >= 0) { 290 | // 291 | // Print number without sign 292 | // 293 | _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); 294 | } 295 | } 296 | } 297 | } 298 | 299 | /********************************************************************* 300 | * 301 | * Public code 302 | * 303 | ********************************************************************** 304 | */ 305 | /********************************************************************* 306 | * 307 | * SEGGER_RTT_vprintf 308 | * 309 | * Function description 310 | * Stores a formatted string in SEGGER RTT control block. 311 | * This data is read by the host. 312 | * 313 | * Parameters 314 | * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 315 | * sFormat Pointer to format string 316 | * pParamList Pointer to the list of arguments for the format string 317 | * 318 | * Return values 319 | * >= 0: Number of bytes which have been stored in the "Up"-buffer. 320 | * < 0: Error 321 | */ 322 | int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { 323 | char c; 324 | SEGGER_RTT_PRINTF_DESC BufferDesc; 325 | int v; 326 | unsigned NumDigits; 327 | unsigned FormatFlags; 328 | unsigned FieldWidth; 329 | char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; 330 | 331 | BufferDesc.pBuffer = acBuffer; 332 | BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; 333 | BufferDesc.Cnt = 0u; 334 | BufferDesc.RTTBufferIndex = BufferIndex; 335 | BufferDesc.ReturnValue = 0; 336 | 337 | do { 338 | c = *sFormat; 339 | sFormat++; 340 | if (c == 0u) { 341 | break; 342 | } 343 | if (c == '%') { 344 | // 345 | // Filter out flags 346 | // 347 | FormatFlags = 0u; 348 | v = 1; 349 | do { 350 | c = *sFormat; 351 | switch (c) { 352 | case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; 353 | case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; 354 | case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; 355 | case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; 356 | default: v = 0; break; 357 | } 358 | } while (v); 359 | // 360 | // filter out field with 361 | // 362 | FieldWidth = 0u; 363 | do { 364 | c = *sFormat; 365 | if ((c < '0') || (c > '9')) { 366 | break; 367 | } 368 | sFormat++; 369 | FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); 370 | } while (1); 371 | 372 | // 373 | // Filter out precision (number of digits to display) 374 | // 375 | NumDigits = 0u; 376 | c = *sFormat; 377 | if (c == '.') { 378 | sFormat++; 379 | do { 380 | c = *sFormat; 381 | if ((c < '0') || (c > '9')) { 382 | break; 383 | } 384 | sFormat++; 385 | NumDigits = NumDigits * 10u + ((unsigned)c - '0'); 386 | } while (1); 387 | } 388 | // 389 | // Filter out length modifier 390 | // 391 | c = *sFormat; 392 | do { 393 | if ((c == 'l') || (c == 'h')) { 394 | sFormat++; 395 | c = *sFormat; 396 | } else { 397 | break; 398 | } 399 | } while (1); 400 | // 401 | // Handle specifiers 402 | // 403 | switch (c) { 404 | case 'c': { 405 | char c0; 406 | v = va_arg(*pParamList, int); 407 | c0 = (char)v; 408 | _StoreChar(&BufferDesc, c0); 409 | break; 410 | } 411 | case 'd': 412 | v = va_arg(*pParamList, int); 413 | _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); 414 | break; 415 | case 'u': 416 | v = va_arg(*pParamList, int); 417 | _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); 418 | break; 419 | case 'x': 420 | case 'X': 421 | v = va_arg(*pParamList, int); 422 | _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); 423 | break; 424 | case 's': 425 | { 426 | const char * s = va_arg(*pParamList, const char *); 427 | do { 428 | c = *s; 429 | s++; 430 | if (c == '\0') { 431 | break; 432 | } 433 | _StoreChar(&BufferDesc, c); 434 | } while (BufferDesc.ReturnValue >= 0); 435 | } 436 | break; 437 | case 'p': 438 | v = va_arg(*pParamList, int); 439 | _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); 440 | break; 441 | case '%': 442 | _StoreChar(&BufferDesc, '%'); 443 | break; 444 | default: 445 | break; 446 | } 447 | sFormat++; 448 | } else { 449 | _StoreChar(&BufferDesc, c); 450 | } 451 | } while (BufferDesc.ReturnValue >= 0); 452 | 453 | if (BufferDesc.ReturnValue > 0) { 454 | // 455 | // Write remaining data, if any 456 | // 457 | if (BufferDesc.Cnt != 0u) { 458 | SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); 459 | } 460 | BufferDesc.ReturnValue += (int)BufferDesc.Cnt; 461 | } 462 | return BufferDesc.ReturnValue; 463 | } 464 | 465 | /********************************************************************* 466 | * 467 | * SEGGER_RTT_printf 468 | * 469 | * Function description 470 | * Stores a formatted string in SEGGER RTT control block. 471 | * This data is read by the host. 472 | * 473 | * Parameters 474 | * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 475 | * sFormat Pointer to format string, followed by the arguments for conversion 476 | * 477 | * Return values 478 | * >= 0: Number of bytes which have been stored in the "Up"-buffer. 479 | * < 0: Error 480 | * 481 | * Notes 482 | * (1) Conversion specifications have following syntax: 483 | * %[flags][FieldWidth][.Precision]ConversionSpecifier 484 | * (2) Supported flags: 485 | * -: Left justify within the field width 486 | * +: Always print sign extension for signed conversions 487 | * 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision 488 | * Supported conversion specifiers: 489 | * c: Print the argument as one char 490 | * d: Print the argument as a signed integer 491 | * u: Print the argument as an unsigned integer 492 | * x: Print the argument as an hexadecimal integer 493 | * s: Print the string pointed to by the argument 494 | * p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) 495 | */ 496 | int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { 497 | int r; 498 | va_list ParamList; 499 | 500 | va_start(ParamList, sFormat); 501 | r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); 502 | va_end(ParamList); 503 | return r; 504 | } 505 | /*************************** End of file ****************************/ 506 | -------------------------------------------------------------------------------- /SConscript: -------------------------------------------------------------------------------- 1 | import os 2 | import rtconfig 3 | from building import * 4 | 5 | cwd = GetCurrentDir() 6 | 7 | src = Split(''' 8 | ''') 9 | 10 | 11 | if GetDepend(['SEGGER_RTT_ENABLE']): 12 | src += Split(''' 13 | RTT/SEGGER_RTT.c 14 | RTT/SEGGER_RTT_printf.c 15 | adapter/drv_rtt.c 16 | ''') 17 | 18 | if GetDepend(['SWO_ENABLE']): 19 | src += Split(''' 20 | adapter/drv_swo.c 21 | ''') 22 | 23 | path = [cwd] 24 | path += [cwd + '/RTT'] 25 | 26 | 27 | LOCAL_CCFLAGS = '' 28 | 29 | group = DefineGroup('SEGGER_RTT', src, depend = [''], CPPPATH = path, LOCAL_CCFLAGS = LOCAL_CCFLAGS) 30 | 31 | Return('group') 32 | -------------------------------------------------------------------------------- /adapter/drv_rtt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-05-23 supperthomas init 9 | * 2022-10-07 supperthomas add the support of RT_USING_SERIAL_V2 10 | * 11 | */ 12 | #include "rtdevice.h" 13 | #include "SEGGER_RTT.h" 14 | 15 | static struct rt_serial_device _serial_jlink_rtt; 16 | 17 | typedef struct 18 | { 19 | struct rt_serial_device *serial; 20 | } drv_jlink_rtt_cfg_t; 21 | 22 | static drv_jlink_rtt_cfg_t m_jlink_rtt_cfg = 23 | { 24 | .serial = &_serial_jlink_rtt, 25 | }; 26 | 27 | 28 | static rt_err_t _rtt_cfg(struct rt_serial_device *serial, struct serial_configure *cfg) 29 | { 30 | return RT_EOK; 31 | } 32 | 33 | static rt_err_t _rtt_ctrl(struct rt_serial_device *serial, int cmd, void *arg) 34 | { 35 | return RT_EOK; 36 | } 37 | static int _rtt_putc(struct rt_serial_device *serial, char c) 38 | { 39 | SEGGER_RTT_PutChar(RTT_DEFAULT_BUFFER_INDEX, c); 40 | return RT_EOK; 41 | } 42 | 43 | static int _rtt_getc(struct rt_serial_device *serial) 44 | { 45 | return SEGGER_RTT_GetKey(); 46 | } 47 | #ifdef RT_USING_SERIAL_V2 48 | ///< RT-Thread Kernel version 49 | #if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 2)) 50 | static rt_ssize_t mcu_transmit(struct rt_serial_device *serial, 51 | rt_uint8_t *buf, 52 | rt_size_t size, 53 | rt_uint32_t tx_flag) 54 | #else /* legacy version macros (<5.0.2) */ 55 | static rt_size_t mcu_transmit(struct rt_serial_device *serial, 56 | rt_uint8_t *buf, 57 | rt_size_t size, 58 | rt_uint32_t tx_flag) 59 | #endif 60 | { 61 | RT_ASSERT(serial != RT_NULL); 62 | RT_ASSERT(buf != RT_NULL); 63 | 64 | SEGGER_RTT_Write(RTT_DEFAULT_BUFFER_INDEX, buf,size); 65 | rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE); 66 | 67 | return size; 68 | } 69 | #endif 70 | 71 | static struct rt_uart_ops _jlink_rtt_ops = 72 | { 73 | _rtt_cfg, 74 | _rtt_ctrl, 75 | _rtt_putc, 76 | _rtt_getc, 77 | #ifdef RT_USING_SERIAL_V2 78 | .transmit = mcu_transmit 79 | #endif 80 | }; 81 | 82 | static void segger_rtt_check(void) 83 | { 84 | #ifdef RT_USING_SERIAL_V2 85 | struct rt_serial_rx_fifo *rx_fifo; 86 | rx_fifo = (struct rt_serial_rx_fifo *)_serial_jlink_rtt.serial_rx; 87 | RT_ASSERT(rx_fifo != RT_NULL); 88 | while (SEGGER_RTT_HasKey()) 89 | { 90 | rt_ringbuffer_putchar(&(rx_fifo->rb), SEGGER_RTT_GetKey()); 91 | rt_hw_serial_isr(&_serial_jlink_rtt, RT_SERIAL_EVENT_RX_IND); 92 | } 93 | #else //RT_USING_SERIAL_V1 94 | while (SEGGER_RTT_HasKey()) 95 | { 96 | rt_hw_serial_isr(&_serial_jlink_rtt, RT_SERIAL_EVENT_RX_IND); 97 | } 98 | #endif 99 | } 100 | 101 | 102 | int rt_hw_jlink_rtt_init(void) 103 | { 104 | SEGGER_RTT_Init(); 105 | rt_thread_idle_sethook(segger_rtt_check); 106 | SEGGER_RTT_SetTerminal(RTT_DEFAULT_TERMINAL_INDEX); 107 | 108 | SEGGER_RTT_ConfigUpBuffer(RTT_DEFAULT_BUFFER_INDEX, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); 109 | 110 | SEGGER_RTT_ConfigDownBuffer(RTT_DEFAULT_BUFFER_INDEX, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); 111 | 112 | struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; 113 | _serial_jlink_rtt.ops = &_jlink_rtt_ops; 114 | _serial_jlink_rtt.config = config; 115 | m_jlink_rtt_cfg.serial = &_serial_jlink_rtt; 116 | rt_hw_serial_register(&_serial_jlink_rtt, "jlinkRtt", \ 117 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &m_jlink_rtt_cfg); 118 | 119 | SEGGER_RTT_printf(0,"\r\n SEGGER_RTT ADDRESS:%p \r\n",&_SEGGER_RTT); 120 | 121 | return 0; 122 | } 123 | 124 | int rt_hw_jlink_console_init(void) 125 | { 126 | rt_hw_jlink_rtt_init(); 127 | rt_console_set_device("jlinkRtt"); 128 | return 0; 129 | } 130 | #ifdef RT_USING_SERIAL_V2 131 | INIT_APP_EXPORT(rt_hw_jlink_console_init); 132 | //if use RT_USING_SERIAL_V2 you can only use console after schedule, the root log missing 133 | #endif 134 | 135 | // if use RT_USING_SERIAL_V1 you can add the code before schedule 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /adapter/drv_swo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-05-24 supperthomas init 9 | * 10 | */ 11 | #include "rtdevice.h" 12 | #include "board.h" 13 | 14 | static struct rt_serial_device _serial_swo; 15 | volatile int32_t ITM_RxBuffer = ITM_RXBUFFER_EMPTY; 16 | typedef struct 17 | { 18 | struct rt_serial_device *serial; 19 | } drv_swo_cfg_t; 20 | 21 | static drv_swo_cfg_t m_swo_cfg = 22 | { 23 | .serial = &_serial_swo, 24 | }; 25 | 26 | 27 | static rt_err_t _swo_cfg(struct rt_serial_device *serial, struct serial_configure *cfg) 28 | { 29 | return RT_EOK; 30 | } 31 | 32 | static rt_err_t _swo_ctrl(struct rt_serial_device *serial, int cmd, void *arg) 33 | { 34 | return RT_EOK; 35 | } 36 | static int _swo_putc(struct rt_serial_device *serial, char c) 37 | { 38 | if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ 39 | ((ITM->TER & (1<PORT[SWO_PORT_NUMBER].u32 == 0) 42 | { 43 | __NOP(); 44 | } 45 | ITM->PORT[SWO_PORT_NUMBER].u8 = (uint8_t)c; 46 | } 47 | return RT_EOK; 48 | } 49 | 50 | static int _swo_getc(struct rt_serial_device *serial) 51 | { 52 | return ITM_ReceiveChar(); 53 | } 54 | 55 | static struct rt_uart_ops _swo_ops = 56 | { 57 | _swo_cfg, 58 | _swo_ctrl, 59 | _swo_putc, 60 | _swo_getc 61 | }; 62 | 63 | static void segger_swo_check(void) 64 | { 65 | if (ITM_CheckChar()) 66 | { 67 | rt_hw_serial_isr(&_serial_swo, RT_SERIAL_EVENT_RX_IND); 68 | } 69 | } 70 | 71 | int rt_hw_swo_init(void) 72 | { 73 | rt_thread_idle_sethook(segger_swo_check); 74 | struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; 75 | _serial_swo.ops = &_swo_ops; 76 | _serial_swo.config = config; 77 | m_swo_cfg.serial = &_serial_swo; 78 | rt_hw_serial_register(&_serial_swo, "SWO", \ 79 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &m_swo_cfg); 80 | return 0; 81 | } 82 | //INIT_BOARD_EXPORT(rt_hw_swo_init); 83 | 84 | -------------------------------------------------------------------------------- /images/image-20210523144320179.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210523144320179.png -------------------------------------------------------------------------------- /images/image-20210523144722163.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210523144722163.png -------------------------------------------------------------------------------- /images/image-20210523145133760.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210523145133760.png -------------------------------------------------------------------------------- /images/image-20210523145308304.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210523145308304.png -------------------------------------------------------------------------------- /images/image-20210523145349136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210523145349136.png -------------------------------------------------------------------------------- /images/image-20210525025001074.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210525025001074.png -------------------------------------------------------------------------------- /images/image-20210525030747681.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210525030747681.png -------------------------------------------------------------------------------- /images/image-20210529222436909.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210529222436909.png -------------------------------------------------------------------------------- /images/image-20210529222511146.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210529222511146.png -------------------------------------------------------------------------------- /images/image-20210529222625567.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210529222625567.png -------------------------------------------------------------------------------- /images/image-20210529222732304.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210529222732304.png -------------------------------------------------------------------------------- /images/image-20210529222806327.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210529222806327.png -------------------------------------------------------------------------------- /images/image-20210529222831650.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20210529222831650.png -------------------------------------------------------------------------------- /images/image-20221007203535784.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supperthomas/RTTHREAD_SEGGER_TOOL/209d52026cfb22a3ae78b981fbd19d19834f175d/images/image-20221007203535784.png --------------------------------------------------------------------------------