├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── chipList.json ├── doc ├── RTT模块代码.png ├── SecureCRT使用教程1.png ├── json文件说明.png ├── shell效果图.png ├── 工具截图.png ├── 技术原理图.png ├── 结果图.bmp └── 芯片列表.png ├── main.py ├── readme.pdf ├── resizeApi.png ├── rtt2telnet.ico ├── rtt2telnet.ui ├── rtt2telnet_driver.py ├── rtt2telnet_ui.py ├── seggerRtt代码包 ├── SEGGER_RTT.c ├── SEGGER_RTT.h ├── SEGGER_RTT_Conf.h └── SEGGER_RTT_printf.c └── 打包完成的exe程序 ├── chipList.json ├── resizeApi.png └── rtt2telnet.exe /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py linguist-language=Python 2 | *.c linguist-language=Python 3 | *.h linguist-language=Python 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 mcujackson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SEGGER_RTT To Telnet 2 | 3 | -- 通过Telnet 转发 SEGGER_RTT 数据 4 | 5 | mcujackson 6 | 7 | 适用于能通过JLink调试的嵌入式芯片,支持SEGGER_RTT 通道0 和 通道1,支持多种目标接口 8 | 包括但不限于以下目标接口类型:SWD、JTAG、CJTAG、FINE,连接速度可选,两路telnet服务器端口号可选。 9 | 10 | ## 1 简述 11 | 12 | ### 1.1 背景 13 | 14 | 在项目调试过程中,遇到串口较少的芯片,除去必须用作与其他外设通讯的串口外,已无剩下可用作调试打印的串口。另外,每次整机调试不仅需要携带j-link 或 st-link此类的烧录工具外,还需要携带串口线用作调试输出,而且大多数情况,为了保证调试串口的问题,许多公司都将芯片输出ttl电平接入RS-232 或 485电平转换芯片转换,使用十分不便,所以开发此工具,用SEGGER_RTT模拟出两路串口,只需通过telnet便可访问两路通道的数据,使用非常方便,绝大多数芯片都能完美兼容。完美解决因串口线连接不稳定而导致调试不便问题。 15 | 16 | ### 1.2 实现方式 17 | 18 | + 1.在工程文件里面加入SEGGER_RTT模块代码,调用读写函数就可以将指定的数据发送给J-link的RTT 19 | + 2.利用本软件开启telnet服务器,并读取指定通道的RTT数据,将数据转发给telnet客户端 20 | + 3.从客户端读取用户输入的信息,将数据转发给j-link的RTT,再由RTT将数据送入嵌入式设备中 21 | 22 | ![实现](doc/技术原理图.png) 23 | 24 | ## 2 移植过程 25 | 26 | ### 2.1 为MCU移植SEGGER_RTT模块 27 | 28 | 首先你需要有一个j-link,在安装完驱动后,可以在 29 | C:\Program Files (x86)\SEGGER\JLink_V632f\Samples\RTT路径下找到 30 | SEGGER_RTT_Vxxxf.zip(xxx是版本号),如果找不到该路径,可以使用搜索工具以 SEGGER_RTT 为关键字搜索,在找到SEGGER_RTT_Vxxxf.zip后,解压该压缩包,在RTT目录找到以下这四个文件 31 | 32 | ![移植](doc/RTT模块代码.png) 33 | 34 | 不过,由于SEGGER_RTT有多个版本,高版本的api做的比较好,所以建议直接用我在工程提供的模块包即可,以上只是说明若有新版本更新,如何去移植最新的版本 35 | 36 | 将这四个文件加入到代码工程中,没出问题的话,你可以正常编译通过,无需修改任何代码,但SEGGER_RTT提供的这部分的代码只实现通道0的数据收发,并没有实现通道1. 37 | 38 | 所以如果想使用通道1,需要在此基础上进行通道的添加,以下为调用提供的api配置的通道1 39 | 40 | ```c 41 | #include "SEGGER_RTT.h" 42 | char rttLogWriteBuffer[512]; 43 | char rttLogReadBuffer[512]; 44 | void rttLogInit(void) 45 | { 46 | //调用SEGGER_RTT的api,配置通道1,若只用作日志输出,可不配置读缓冲,减少RAM空间 47 | //其中 1 代表通道1 ,rttLogWriteBuffer为该缓冲区的写buffer,512为该buffer的大小,"Log"代表通道1的名字 48 | SEGGER_RTT_ConfigUpBuffer(1, "Log", rttLogWriteBuffer, 512, SEGGER_RTT_MODE_DEFAULT);//配置写缓冲 49 | 50 | //rttLogReadBuffer为该缓冲区的读buffer 51 | SEGGER_RTT_ConfigDownBuffer(1, "Log", rttLogReadBuffer, 512, SEGGER_RTT_MODE_DEFAULT);//配置读缓冲 52 | } 53 | ``` 54 | 55 | 另外可根据需求修改通道0的缓冲区大小,在#include "SEGGER_RTT_Conf.h"文件中,个人修改为512,基本满足数据收发需求 56 | 57 | ```c 58 | #define BUFFER_SIZE_UP (512) // Size of the buffer for terminal output of target, up to host (Default: 1k) 59 | #define BUFFER_SIZE_DOWN (512) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) 60 | ``` 61 | 62 | 至此,SEGGER_RTT 模块就简单的移植完成了。 63 | 为了方便测试,在main.c函数中需要调用SEGGER_RTT的发送函数当做测试,可以使用 64 | SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); 65 | BufferIndex代表通道号,后面的填写跟printf一模一样(不过对浮点型的支持似乎不是那么好,有兴趣的同学可以多试试 66 | 个人的例子是用它所提供的写函数 67 | 68 | ```c 69 | while (1) 70 | { 71 | while (SEGGER_RTT_GetAvailWriteSpace(0) < 24)//判断通道 0 写buffer是否有足够的空间写 72 | { 73 | HAL_Delay(1);//你自己的延迟函数 74 | } 75 | SEGGER_RTT_Write(0, "channel0:mcujackson666\r\n", 24);//将数据发送 76 | 77 | while (SEGGER_RTT_GetAvailWriteSpace(1) < 24)//判断通道 1 写buffer是否有足够的空间写 78 | { 79 | HAL_Delay(1);//你自己的延迟函数 80 | } 81 | SEGGER_RTT_Write(1, "channel1:mcujackson666\r\n", 24);//将数据发送 82 | HAL_Delay(1000); 83 | } 84 | ``` 85 | 86 | ### 2.2 使用RTT 转 Telnet工具 生成两个通道的Telnet服务 87 | 88 | ![使用](doc/工具截图.png) 89 | 90 | + 1.首先打开工程目录下的chipList.json 91 | 这是一个json格式的文件,可以将自己常用的芯片型号添加进列表中,记得加上逗号哦,不然程序解析错误可能会出现奔溃的情况,还可以将 "default":"STM32L031G6" 修改为自己最常用的芯片型号,这样在程序打开的时候就会直接选择该型号的芯片 92 | 93 | ![使用](doc/json文件说明.png) 94 | 95 | ![使用](doc/芯片列表.png) 96 | 97 | 若无需修改端口,直接点击开启按钮即可 98 | 99 | ### 2.3 使用SecureCRT登录Telnet服务器 100 | 101 | 1.如果在本机开启该软件,可以用直接用127.0.0.1的地址即可登录到telnet服务器,如下图 102 | ![使用](doc/SecureCRT使用教程1.png) 103 | 104 | ![使用](doc/结果图.bmp) 105 | 106 | ## 3 结合Shell使用 107 | 108 | 暂无,后续会进行补充 109 | 有兴趣的同学可以使用letter大神写的嵌入式shell 110 | 111 | https://github.com/NevermindZZT/letter-shell 112 | 113 | 结合本软件可以实现比较实用的调试功能,下面先放一张效果图 114 | 115 | ![shell](doc/shell效果图.png) 116 | 117 | ## 4 修改记录 118 | 119 | 2020/06/09 1.0 120 | 121 | - 第一次提交 122 | -------------------------------------------------------------------------------- /chipList.json: -------------------------------------------------------------------------------- 1 | { 2 | "chipList": 3 | [ 4 | "STM32L031G6", 5 | "STM32F407IG", 6 | "STM32F407VE", 7 | "STM32F407ZG", 8 | "STM32F427ZI" 9 | ], 10 | 11 | "default":"STM32L031G6" 12 | } 13 | -------------------------------------------------------------------------------- /doc/RTT模块代码.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/RTT模块代码.png -------------------------------------------------------------------------------- /doc/SecureCRT使用教程1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/SecureCRT使用教程1.png -------------------------------------------------------------------------------- /doc/json文件说明.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/json文件说明.png -------------------------------------------------------------------------------- /doc/shell效果图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/shell效果图.png -------------------------------------------------------------------------------- /doc/工具截图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/工具截图.png -------------------------------------------------------------------------------- /doc/技术原理图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/技术原理图.png -------------------------------------------------------------------------------- /doc/结果图.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/结果图.bmp -------------------------------------------------------------------------------- /doc/芯片列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/doc/芯片列表.png -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from PyQt5.QtWidgets import QApplication, QMainWindow, QComboBox, QWidget, QSystemTrayIcon, QMenu, QAction, QMessageBox 4 | from PyQt5 import QtGui 5 | import rtt2telnet_ui 6 | import rtt2telnet_driver 7 | import pylink 8 | import logging 9 | import json 10 | 11 | #初始化log的格式 12 | logfmt = "%(asctime)s %(filename)s %(funcName)s: %(levelname)s: %(message)s" 13 | logdatafmt = "%Y-%m-%d %H:%M:%S" 14 | 15 | #接口类型对照表 16 | targetInterface = { 17 | "SWD": pylink.enums.JLinkInterfaces.SWD, 18 | "JTAG": pylink.enums.JLinkInterfaces.JTAG, 19 | "cJTAG": pylink.enums.JLinkInterfaces.C2, 20 | "FINE": pylink.enums.JLinkInterfaces.FINE 21 | } 22 | 23 | #负责存储芯片类型列表 24 | chipList = [] 25 | #默认下拉框启动后默认的芯片类型列表 26 | defalutChipName = "" 27 | 28 | 29 | class Control(): 30 | def __init__(self, ui, MainWindow): 31 | self.ui = ui 32 | self.MainWindow = MainWindow 33 | #开关按钮 34 | ui.switchButton.clicked.connect(self.__switchRttToTelnet) 35 | #隐藏到托盘按钮 36 | ui.hideButton.clicked.connect(self.__hide) 37 | #加入芯片信号型号 38 | ui.chipCombox.addItems(chipList) 39 | #设置当前默认芯片型号 40 | ui.chipCombox.setCurrentText(defalutChipName) 41 | #初始化托盘图标 42 | self.__trayIcon() 43 | 44 | def __switchRttToTelnet(self): 45 | """开启按钮按下后执行的函数. 46 | 47 | 包括创建通道0、1的telnet服务器 48 | 创建rtt转telnet服务 49 | 已经关闭后所执行的收尾操作 50 | 51 | Args: 52 | self (Control): the ``Control`` instance 53 | Returns: 54 | None 55 | """ 56 | if self.ui.switchButton.text() == "开启": 57 | #创建通道0对应的tcp服务器 58 | self.telnetObj1 = rtt2telnet_driver.TcpServer( 59 | '0.0.0.0', int(self.ui.channel0Port.text()), 2048) 60 | #创建通道1对应的tcp服务器 61 | self.telnetObj2 = rtt2telnet_driver.TcpServer( 62 | '0.0.0.0', int(self.ui.channel1Port.text()), 2048) 63 | #创建rtt2转telnet服务 64 | self.rtt2telnetController = rtt2telnet_driver.RttToTelnet( 65 | device=self.ui.chipCombox.currentText(), #芯片类型 66 | interface=targetInterface[ 67 | self.ui.interfaceCombox.currentText()], #接口类型 68 | speed=int(self.ui.speedCombox.currentText().replace("kHz","")), #速度 69 | reset=True, #连接后复位 70 | telnetObj1=self.telnetObj1, 71 | telnetObj2=self.telnetObj2, 72 | ) 73 | if self.rtt2telnetController.isActive() == False: 74 | try: 75 | #开始rtt转telnet服务 76 | self.rtt2telnetController.start() 77 | except Exception as e: 78 | #开启失败必须删除整个服务对象 79 | del self.rtt2telnetController 80 | #删除通道0对应的tcp服务器 81 | self.telnetObj1.stop() 82 | del self.telnetObj1 83 | #删除通道1对应的tcp服务器 84 | self.telnetObj2.stop() 85 | del self.telnetObj2 86 | logging.exception(e) 87 | QMessageBox.information(self.MainWindow, "警告", 88 | "开启失败,请检查jlink是否连接上芯片或者网络端口是否被占用") 89 | return 90 | else: 91 | self.telnetObj1.stop() 92 | del self.telnetObj1 93 | self.telnetObj2.stop() 94 | del self.telnetObj2 95 | self.ui.switchButton.setText("关闭") 96 | 97 | elif self.ui.switchButton.text() == "关闭": 98 | if self.rtt2telnetController.isActive() == True: 99 | self.rtt2telnetController.stop() 100 | del self.rtt2telnetController 101 | self.telnetObj1.stop() 102 | del self.telnetObj1 103 | self.telnetObj2.stop() 104 | del self.telnetObj2 105 | self.ui.switchButton.setText("开启") 106 | 107 | def __hide(self): 108 | """隐藏窗口. 109 | 110 | 将窗口隐藏并作出气泡提示 111 | 112 | Args: 113 | self (Control): the ``Control`` instance 114 | Returns: 115 | None 116 | 117 | """ 118 | #隐藏窗口 119 | self.MainWindow.hide() 120 | #隐藏后的气泡提示 121 | self.tuopan.showMessage(u"提示", '双击再次打开窗口', 122 | icon=1) #icon的值 0没有图标 1是提示 2是警告 3是错误 123 | 124 | def __trayIcon(self): 125 | """创建托盘图标. 126 | 127 | Args: 128 | self (Control): the ``Control`` instance 129 | Returns: 130 | None 131 | 132 | """ 133 | #托盘 134 | self.tuopan = QSystemTrayIcon(self.MainWindow) #创建托盘 135 | self.tuopan.setIcon(QtGui.QIcon(r'./resizeApi.png')) #设置托盘图标 136 | # 弹出的信息被点击就会调用messageClicked连接的函数 137 | #tuopan.messageClicked.connect(self.message) 138 | 139 | #托盘图标被激活所执行的回调 140 | self.tuopan.activated.connect(self.__iconActivated) 141 | #设置提示信息 142 | self.tuopan.setToolTip(u'rtt2telnet') 143 | #创建托盘的右键菜单 144 | #tpMenu = QMenu() 145 | # a1 = QAction(QtGui.QIcon('exit.png'), u'关于', self.MainWindow) #添加一级菜单动作选项(关于程序) 146 | # a1.triggered.connect(self.about) 147 | # a2 = QAction(QtGui.QIcon('exit.png'), u'退出', self.MainWindow) #添加一级菜单动作选项(退出程序) 148 | # a2.triggered.connect(self.quit) 149 | # tpMenu.addAction(a1) 150 | # tpMenu.addAction(a2) 151 | #tuopan.setContextMenu(tpMenu) #把tpMenu设定为托盘的右键菜单 152 | self.tuopan.show() #显示托盘 153 | 154 | def __iconActivated(self, reason): 155 | """激活托盘图标所执行的操作 156 | 157 | Args: 158 | self (Control): the ``Control`` instance 159 | reason (QSystemTrayIcon) 事件类型 160 | Returns: 161 | None 162 | """ 163 | if reason == QSystemTrayIcon.DoubleClick: #双击 显示或隐藏窗口 164 | self.__windowShow() 165 | elif reason == QSystemTrayIcon.Trigger: # 单击无效 166 | pass 167 | 168 | #响应托盘双击,最大最小化界面 169 | def __windowShow(self): 170 | """托盘双击事件. 171 | 172 | Args: 173 | self (Control): the ``Control`` instance 174 | Returns: 175 | None 176 | 177 | """ 178 | if self.MainWindow.isMinimized() or not self.MainWindow.isVisible(): 179 | #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面) 180 | self.MainWindow.showNormal() 181 | self.MainWindow.activateWindow() 182 | else: 183 | #直接隐藏 184 | self.MainWindow.hide() 185 | 186 | 187 | def loadChipList(): 188 | """加载芯片型号列表. 189 | 190 | 从当前目录下的chipList.json中读取列表,并填入全局 191 | 变量chipList中 192 | 193 | Args: 194 | None 195 | Returns: 196 | None 197 | 198 | """ 199 | global chipList 200 | global defalutChipName 201 | chipListFile = os.path.abspath(os.curdir) 202 | file = chipListFile + '/chipList.json' 203 | if os.path.exists(file): 204 | with open(file, 'r+', encoding='utf-8') as f: 205 | try: 206 | data = json.load(f) 207 | except Exception as e: 208 | logging.exception(e) 209 | exit(-1) 210 | if "chipList" in data: 211 | chipList = chipList + (data["chipList"]) 212 | print(data["chipList"]) 213 | if "default" in data: 214 | defalutChipName = data["default"] 215 | 216 | 217 | def initLog(): 218 | """初始log日志. 219 | 220 | 将log日志的存放位置定向到当前目录下的rttToTelnet.log中 221 | 222 | Args: 223 | None 224 | Returns: 225 | None 226 | 227 | """ 228 | logfile = '.\\rttToTelnet.log' 229 | if not os.path.exists( 230 | logfile) or os.path.getsize(logfile) > 1 * 1024 * 1024: 231 | with open(logfile, 'w') as f: 232 | pass 233 | 234 | logging.basicConfig(filename = logfile, filemode = 'a', \ 235 | format = logfmt, datefmt = logdatafmt, level = logging.INFO) 236 | 237 | 238 | if __name__ == '__main__': 239 | #加载芯片型号列表 240 | loadChipList() 241 | #log日志重定向 242 | initLog() 243 | app = QApplication(sys.argv) 244 | MainWindow = QMainWindow() 245 | 246 | ui = rtt2telnet_ui.Ui_MainWindow() 247 | ui.setupUi(MainWindow) 248 | control = Control(ui, MainWindow) 249 | #设置图标 250 | MainWindow.setWindowIcon(QtGui.QIcon(r'./resizeApi.png')) 251 | MainWindow.show() 252 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /readme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/readme.pdf -------------------------------------------------------------------------------- /resizeApi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/resizeApi.png -------------------------------------------------------------------------------- /rtt2telnet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/rtt2telnet.ico -------------------------------------------------------------------------------- /rtt2telnet.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 273 10 | 208 11 | 12 | 13 | 14 | RTT转Telnet工具 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 13 27 | 28 | 29 | 30 | 芯片型号: 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 13 46 | 47 | 48 | 49 | 目标接口: 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | SWD 58 | 59 | 60 | 61 | 62 | JTAG 63 | 64 | 65 | 66 | 67 | cJTAG 68 | 69 | 70 | 71 | 72 | FINE 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 13 86 | 87 | 88 | 89 | 速度: 90 | 91 | 92 | 93 | 94 | 95 | 96 | 20 97 | 98 | 99 | 100 | 5kHz 101 | 102 | 103 | 104 | 105 | 10kHz 106 | 107 | 108 | 109 | 110 | 20kHz 111 | 112 | 113 | 114 | 115 | 30kHz 116 | 117 | 118 | 119 | 120 | 50kHz 121 | 122 | 123 | 124 | 125 | 100kHz 126 | 127 | 128 | 129 | 130 | 200kHz 131 | 132 | 133 | 134 | 135 | 300kHz 136 | 137 | 138 | 139 | 140 | 400kHz 141 | 142 | 143 | 144 | 145 | 500kHz 146 | 147 | 148 | 149 | 150 | 600kHz 151 | 152 | 153 | 154 | 155 | 650kHz 156 | 157 | 158 | 159 | 160 | 750kHz 161 | 162 | 163 | 164 | 165 | 900kHz 166 | 167 | 168 | 169 | 170 | 1000kHz 171 | 172 | 173 | 174 | 175 | 1334kHz 176 | 177 | 178 | 179 | 180 | 1600kHz 181 | 182 | 183 | 184 | 185 | 2000kHz 186 | 187 | 188 | 189 | 190 | 2667kHz 191 | 192 | 193 | 194 | 195 | 3200kHz 196 | 197 | 198 | 199 | 200 | 4000kHz 201 | 202 | 203 | 204 | 205 | 4800kHz 206 | 207 | 208 | 209 | 210 | 5334kHz 211 | 212 | 213 | 214 | 215 | 6000kHz 216 | 217 | 218 | 219 | 220 | 8000kHz 221 | 222 | 223 | 224 | 225 | 9600kHz 226 | 227 | 228 | 229 | 230 | 12000kHz 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 13 244 | 245 | 246 | 247 | 通道1对应端口号: 248 | 249 | 250 | 251 | 252 | 253 | 254 | 6198 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 13 267 | 268 | 269 | 270 | 通道2对应端口号: 271 | 272 | 273 | 274 | 275 | 276 | 277 | 6199 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 开启 289 | 290 | 291 | 292 | 293 | 294 | 295 | 隐入托盘 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 0 309 | 0 310 | 273 311 | 23 312 | 313 | 314 | 315 | 316 | 作者 317 | 318 | 319 | 320 | 邮箱 321 | 322 | 323 | 324 | 325 | 326 | 姓名 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 619808090@qq.com 338 | 339 | 340 | 341 | 342 | Driver 343 | 344 | 345 | 346 | 347 | 348 | 349 | -------------------------------------------------------------------------------- /rtt2telnet_driver.py: -------------------------------------------------------------------------------- 1 | import pylink 2 | import time 3 | import threading 4 | import logging 5 | from socket import * 6 | MAX_CONNECT_NUM = 2048 #最大监听数量 7 | 8 | 9 | class TcpServer(): 10 | def __init__(self, hostAddr, port, bufferSize): 11 | 12 | """初始对象 13 | 14 | Args: 15 | self (TcpServer): the ``TcpServer`` instance 16 | hostAddr (str):主机地址 17 | port(int):端口号 18 | bufferSize(int):一次读取的缓冲带下 19 | 20 | Returns: 21 | None 22 | """ 23 | 24 | #主机地址 25 | self.hostAddr = hostAddr 26 | #绑定的端口 27 | self.port = port 28 | #一次性所读数据数量 29 | self.bufferSize = bufferSize 30 | 31 | self.tcpSocket = socket(AF_INET, SOCK_STREAM) 32 | self.tcpSocket.bind((hostAddr, port)) 33 | self.tcpSocket.listen(MAX_CONNECT_NUM) 34 | 35 | self.currentTcpClientSocket = None 36 | 37 | #开启处理线程 38 | self.acceptTaskSwitch = True 39 | self.acceptThread = threading.Thread(target=self.__acceptTask, 40 | daemon=True, 41 | args=[self.tcpSocket]) 42 | self.acceptThread.start() 43 | 44 | def __del__(self): 45 | """删除对象 46 | 47 | Args: 48 | self (TcpServer): the ``TcpServer`` instance 49 | 50 | Returns: 51 | None 52 | """ 53 | #在删除对象的时候,需将所创建的其他对象删除干净 54 | if self.currentTcpClientSocket != None: 55 | self.currentTcpClientSocket.close() 56 | self.tcpSocket.close() 57 | self.acceptTaskSwitch = False 58 | self.acceptThread.join() 59 | 60 | def stop(self): 61 | """结束telnet处理线程 62 | 63 | Args: 64 | self (TcpServer): the ``TcpServer`` instance 65 | 66 | Returns: 67 | None 68 | """ 69 | self.acceptTaskSwitch = False 70 | self.tcpSocket.close() 71 | self.acceptThread.join() 72 | 73 | def __acceptTask(self, tcpSocket): 74 | 75 | """telnet监听结果处理过程 76 | 77 | 主要实现在另外一个链接发起后,断开当前链接,只保持一个链接供用户的操作 78 | 79 | Args: 80 | self (TcpServer): the ``TcpServer`` instance 81 | tcpSocket(socket):套接字对象 82 | Returns: 83 | None 84 | """ 85 | 86 | while self.acceptTaskSwitch == True: 87 | try: 88 | #持续监听 89 | tcpClientSocket, addr = tcpSocket.accept() 90 | print("连接:", addr) 91 | 92 | #更新新的socket,在另外一个链接发起连接时,会关闭现有的链接 93 | if self.currentTcpClientSocket == None: 94 | self.currentTcpClientSocket = tcpClientSocket 95 | else: 96 | #关闭上一个socket 97 | self.currentTcpClientSocket.close() 98 | self.currentTcpClientSocket = tcpClientSocket 99 | 100 | except Exception as e: 101 | logging.error(e, exc_info=True) 102 | print(e) 103 | 104 | def write(self, data): 105 | 106 | """telnet服务器发送数据给客户端 107 | 108 | 主要实现在另外一个链接发起后,断开当前链接,只保持一个链接供用户的操作 109 | 110 | Args: 111 | self (TcpServer): the ``TcpServer`` instance 112 | tcpSocket(socket):套接字对象 113 | 114 | Returns: 115 | None 116 | """ 117 | if self.currentTcpClientSocket != None: 118 | self.currentTcpClientSocket.send(data) 119 | 120 | def read(self): 121 | try: 122 | if self.currentTcpClientSocket == None: 123 | time.sleep(1) #如果还没建立起链接,则返回none 124 | return None 125 | data = self.currentTcpClientSocket.recv(self.bufferSize) 126 | if not data: 127 | return None 128 | return data 129 | except Exception as e: #链接在阻塞读的时候被结束,会以异常的方式通知 130 | print(e) 131 | self.currentTcpClientSocket = None 132 | return None 133 | 134 | 135 | class RttToTelnet(): 136 | def __init__(self, 137 | device, 138 | telnetObj1, 139 | telnetObj2, 140 | interface=pylink.enums.JLinkInterfaces.SWD, 141 | speed=12000, 142 | reset=True): 143 | # 目标芯片名字 144 | self.device = device 145 | # 调试口 146 | self._interface = interface 147 | # 连接速率 148 | self._speed = speed 149 | # 复位标志 150 | self._reset = reset 151 | 152 | # segger rtt上下通道缓存大小 153 | self.upbufferSize = 8 * 1024 154 | self.downbufferSize = 8 * 1024 155 | 156 | # 两个telnet服务器操作引用 157 | self.telnetObj1 = telnetObj1 158 | self.telnetObj2 = telnetObj2 159 | # 线程 160 | self.rtt2telnet = None 161 | self.telnet2rtt = None 162 | self.rtt2telnet2 = None 163 | self.telnet2rtt2 = None 164 | 165 | #线程开关 166 | self.threadSwitch = False 167 | 168 | try: 169 | self.jlink = pylink.JLink() 170 | except: 171 | logging.error('Find jlink dll failed', exc_info=True) 172 | raise 173 | 174 | def rttToTelnet(self): 175 | 176 | while self.threadSwitch == True: 177 | try: 178 | rtt_recv = self.jlink.rtt_read(0, self.upbufferSize) 179 | except: 180 | raise Exception("Jlink rtt read error") 181 | 182 | if len(rtt_recv) == 0: 183 | continue 184 | try: 185 | self.telnetObj1.write(bytes(rtt_recv)) 186 | except: 187 | raise Exception("Telnet write error") 188 | 189 | def telnetToRtt(self): 190 | 191 | while self.threadSwitch == True: 192 | data = self.telnetObj1.read() 193 | if data == None or len(data) == 0: 194 | continue 195 | 196 | #过滤掉telnet连接成功发过来的握手信号 197 | if data == b'\xff\xfd\x03\xff\xfb\x18': 198 | continue 199 | 200 | try: 201 | #如果mcu的SEGGER_RTT并没有开启指定通道,则千万不可调用rtt_write函数 202 | #若通道0开启,SizeOfBuffer缓冲区大小不应为0 203 | desc = self.jlink.rtt_get_buf_descriptor(0, True) 204 | if desc.SizeOfBuffer == 0: 205 | continue 206 | except Exception as e: 207 | 208 | print(e) 209 | logging.error(e, exc_info=True) 210 | 211 | # 将读出的数据写入到rtt 212 | write_index = 0 213 | 214 | #确保所有字节数据全部写入 215 | while write_index < len(data): 216 | try: 217 | bytes_written = self.jlink.rtt_write(0, data[write_index:]) 218 | except: 219 | raise Exception("Jlink rtt write error") 220 | 221 | write_index = write_index + bytes_written 222 | 223 | def rttToTelnet2(self): 224 | while self.threadSwitch == True: 225 | try: 226 | rtt_recv = self.jlink.rtt_read(1, self.upbufferSize) 227 | except: 228 | raise Exception("Jlink rtt read error") 229 | 230 | if len(rtt_recv) == 0: 231 | continue 232 | try: 233 | self.telnetObj2.write(bytes(rtt_recv)) 234 | except: 235 | raise Exception("Telnet write error") 236 | 237 | def telnetToRtt2(self): 238 | while self.threadSwitch == True: 239 | 240 | data = self.telnetObj2.read() 241 | if data == None or len(data) == 0: 242 | continue 243 | 244 | if data == b'\xff\xfd\x03\xff\xfb\x18': 245 | continue 246 | 247 | try: 248 | desc = self.jlink.rtt_get_buf_descriptor(1, True) 249 | if desc.SizeOfBuffer == 0: 250 | continue 251 | except Exception as e: 252 | print(e) 253 | logging.error(e, exc_info=True) 254 | 255 | write_index = 0 256 | while write_index < len(data): 257 | try: 258 | bytes_written = self.jlink.rtt_write(1, data[write_index:]) 259 | except: 260 | raise Exception("Jlink rtt write error") 261 | 262 | write_index = write_index + bytes_written 263 | 264 | def start(self): 265 | try: 266 | if self.jlink.connected() == False: 267 | # 加载jlinkARM.dll 268 | self.jlink.open() 269 | # 设置连接速率 270 | if self.jlink.set_speed(self._speed) == False: 271 | logging.error('Set speed failed', exc_info=True) 272 | raise 273 | if self.jlink.set_tif(self._interface) == False: 274 | logging.error('Set interface failed', exc_info=True) 275 | raise 276 | 277 | try: 278 | # 连接目标芯片 279 | self.jlink.connect(self.device) 280 | # 启动RTT,对于RTT的任何操作都需要在RTT启动后进行 281 | self.jlink.rtt_start() 282 | 283 | if self._reset == True: 284 | # 复位一下目标芯片,复位后不要停止芯片,保证后续操作的稳定性 285 | self.jlink.reset(halt=False) 286 | 287 | except Exception as e: 288 | logging.error('Connect target failed', exc_info=True) 289 | raise 290 | 291 | except pylink.errors.JLinkException as errors: 292 | logging.error('Open jlink failed', exc_info=True) 293 | raise 294 | 295 | #开启通道0的处理线程 296 | self.threadSwitch = True 297 | self.rtt2telnet = threading.Thread(target=self.rttToTelnet, 298 | daemon=True) 299 | self.telnet2rtt = threading.Thread(target=self.telnetToRtt, 300 | daemon=True) 301 | self.rtt2telnet.start() 302 | self.telnet2rtt.start() 303 | 304 | #开启通道1的处理线程 305 | self.rtt2telnet2 = threading.Thread(target=self.rttToTelnet2, 306 | daemon=True) 307 | self.telnet2rtt2 = threading.Thread(target=self.telnetToRtt2, 308 | daemon=True) 309 | self.rtt2telnet2.start() 310 | self.telnet2rtt2.start() 311 | 312 | 313 | def stop(self): 314 | 315 | #需先将socket关闭,使telnet服务在读阻塞中退出 316 | if self.telnetObj1.currentTcpClientSocket: 317 | self.telnetObj1.currentTcpClientSocket.close() 318 | 319 | if self.telnetObj2.currentTcpClientSocket: 320 | self.telnetObj2.currentTcpClientSocket.close() 321 | 322 | #关闭通道0和通道1的处理线程 323 | self.threadSwitch = False 324 | # 等待线程结束 325 | if self.rtt2telnet.is_alive(): 326 | self.rtt2telnet.join() 327 | 328 | if self.telnet2rtt.is_alive(): 329 | self.telnet2rtt.join() 330 | 331 | # 等待线程结束 332 | if self.rtt2telnet2.is_alive(): 333 | self.rtt2telnet2.join() 334 | 335 | if self.telnet2rtt2.is_alive(): 336 | self.telnet2rtt2.join() 337 | 338 | try: 339 | if self.jlink.connected() == True: 340 | # 使用完后停止RTT 341 | self.jlink.rtt_stop() 342 | # 释放之前加载的jlinkARM.dll 343 | self.jlink.close() 344 | 345 | except pylink.errors.JLinkException: 346 | logging.error('Disconnect target failed', exc_info=True) 347 | pass 348 | 349 | def __del__(self): 350 | self.jlink.close() 351 | #在下次的对象创建之前必须先删除本对象,毕竟设备只有一个 352 | del self.jlink 353 | 354 | def isActive(self): 355 | return self.threadSwitch 356 | 357 | -------------------------------------------------------------------------------- /rtt2telnet_ui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'rtt2telnet.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.13.0 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | 10 | from PyQt5 import QtCore, QtGui, QtWidgets 11 | 12 | 13 | class Ui_MainWindow(object): 14 | def setupUi(self, MainWindow): 15 | MainWindow.setObjectName("MainWindow") 16 | MainWindow.resize(273, 208) 17 | self.centralwidget = QtWidgets.QWidget(MainWindow) 18 | self.centralwidget.setObjectName("centralwidget") 19 | self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.centralwidget) 20 | self.horizontalLayout_7.setObjectName("horizontalLayout_7") 21 | self.verticalLayout = QtWidgets.QVBoxLayout() 22 | self.verticalLayout.setObjectName("verticalLayout") 23 | self.horizontalLayout = QtWidgets.QHBoxLayout() 24 | self.horizontalLayout.setObjectName("horizontalLayout") 25 | self.label = QtWidgets.QLabel(self.centralwidget) 26 | font = QtGui.QFont() 27 | font.setPointSize(13) 28 | self.label.setFont(font) 29 | self.label.setObjectName("label") 30 | self.horizontalLayout.addWidget(self.label) 31 | self.chipCombox = QtWidgets.QComboBox(self.centralwidget) 32 | self.chipCombox.setObjectName("chipCombox") 33 | self.horizontalLayout.addWidget(self.chipCombox) 34 | self.verticalLayout.addLayout(self.horizontalLayout) 35 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 36 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 37 | self.label_2 = QtWidgets.QLabel(self.centralwidget) 38 | font = QtGui.QFont() 39 | font.setPointSize(13) 40 | self.label_2.setFont(font) 41 | self.label_2.setObjectName("label_2") 42 | self.horizontalLayout_2.addWidget(self.label_2) 43 | self.interfaceCombox = QtWidgets.QComboBox(self.centralwidget) 44 | self.interfaceCombox.setObjectName("interfaceCombox") 45 | self.interfaceCombox.addItem("") 46 | self.interfaceCombox.addItem("") 47 | self.interfaceCombox.addItem("") 48 | self.interfaceCombox.addItem("") 49 | self.horizontalLayout_2.addWidget(self.interfaceCombox) 50 | self.verticalLayout.addLayout(self.horizontalLayout_2) 51 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout() 52 | self.horizontalLayout_3.setObjectName("horizontalLayout_3") 53 | self.label_3 = QtWidgets.QLabel(self.centralwidget) 54 | font = QtGui.QFont() 55 | font.setPointSize(13) 56 | self.label_3.setFont(font) 57 | self.label_3.setObjectName("label_3") 58 | self.horizontalLayout_3.addWidget(self.label_3) 59 | self.speedCombox = QtWidgets.QComboBox(self.centralwidget) 60 | self.speedCombox.setObjectName("speedCombox") 61 | self.speedCombox.addItem("") 62 | self.speedCombox.addItem("") 63 | self.speedCombox.addItem("") 64 | self.speedCombox.addItem("") 65 | self.speedCombox.addItem("") 66 | self.speedCombox.addItem("") 67 | self.speedCombox.addItem("") 68 | self.speedCombox.addItem("") 69 | self.speedCombox.addItem("") 70 | self.speedCombox.addItem("") 71 | self.speedCombox.addItem("") 72 | self.speedCombox.addItem("") 73 | self.speedCombox.addItem("") 74 | self.speedCombox.addItem("") 75 | self.speedCombox.addItem("") 76 | self.speedCombox.addItem("") 77 | self.speedCombox.addItem("") 78 | self.speedCombox.addItem("") 79 | self.speedCombox.addItem("") 80 | self.speedCombox.addItem("") 81 | self.speedCombox.addItem("") 82 | self.speedCombox.addItem("") 83 | self.speedCombox.addItem("") 84 | self.speedCombox.addItem("") 85 | self.speedCombox.addItem("") 86 | self.speedCombox.addItem("") 87 | self.speedCombox.addItem("") 88 | self.horizontalLayout_3.addWidget(self.speedCombox) 89 | self.verticalLayout.addLayout(self.horizontalLayout_3) 90 | self.horizontalLayout_4 = QtWidgets.QHBoxLayout() 91 | self.horizontalLayout_4.setObjectName("horizontalLayout_4") 92 | self.label_4 = QtWidgets.QLabel(self.centralwidget) 93 | font = QtGui.QFont() 94 | font.setPointSize(13) 95 | self.label_4.setFont(font) 96 | self.label_4.setObjectName("label_4") 97 | self.horizontalLayout_4.addWidget(self.label_4) 98 | self.channel0Port = QtWidgets.QLineEdit(self.centralwidget) 99 | self.channel0Port.setObjectName("channel0Port") 100 | self.horizontalLayout_4.addWidget(self.channel0Port) 101 | self.verticalLayout.addLayout(self.horizontalLayout_4) 102 | self.horizontalLayout_5 = QtWidgets.QHBoxLayout() 103 | self.horizontalLayout_5.setObjectName("horizontalLayout_5") 104 | self.label_5 = QtWidgets.QLabel(self.centralwidget) 105 | font = QtGui.QFont() 106 | font.setPointSize(13) 107 | self.label_5.setFont(font) 108 | self.label_5.setObjectName("label_5") 109 | self.horizontalLayout_5.addWidget(self.label_5) 110 | self.channel1Port = QtWidgets.QLineEdit(self.centralwidget) 111 | self.channel1Port.setObjectName("channel1Port") 112 | self.horizontalLayout_5.addWidget(self.channel1Port) 113 | self.verticalLayout.addLayout(self.horizontalLayout_5) 114 | self.horizontalLayout_6 = QtWidgets.QHBoxLayout() 115 | self.horizontalLayout_6.setObjectName("horizontalLayout_6") 116 | self.switchButton = QtWidgets.QPushButton(self.centralwidget) 117 | self.switchButton.setObjectName("switchButton") 118 | self.horizontalLayout_6.addWidget(self.switchButton) 119 | self.hideButton = QtWidgets.QPushButton(self.centralwidget) 120 | self.hideButton.setObjectName("hideButton") 121 | self.horizontalLayout_6.addWidget(self.hideButton) 122 | self.verticalLayout.addLayout(self.horizontalLayout_6) 123 | self.horizontalLayout_7.addLayout(self.verticalLayout) 124 | MainWindow.setCentralWidget(self.centralwidget) 125 | self.menubar = QtWidgets.QMenuBar(MainWindow) 126 | self.menubar.setGeometry(QtCore.QRect(0, 0, 273, 23)) 127 | self.menubar.setObjectName("menubar") 128 | self.menu = QtWidgets.QMenu(self.menubar) 129 | self.menu.setObjectName("menu") 130 | self.menu_2 = QtWidgets.QMenu(self.menu) 131 | self.menu_2.setObjectName("menu_2") 132 | self.menu_3 = QtWidgets.QMenu(self.menu) 133 | self.menu_3.setObjectName("menu_3") 134 | MainWindow.setMenuBar(self.menubar) 135 | self.action619808090_qq_com = QtWidgets.QAction(MainWindow) 136 | self.action619808090_qq_com.setObjectName("action619808090_qq_com") 137 | self.actionDriver = QtWidgets.QAction(MainWindow) 138 | self.actionDriver.setObjectName("actionDriver") 139 | self.menu_2.addAction(self.action619808090_qq_com) 140 | self.menu_3.addAction(self.actionDriver) 141 | self.menu.addAction(self.menu_2.menuAction()) 142 | self.menu.addAction(self.menu_3.menuAction()) 143 | self.menubar.addAction(self.menu.menuAction()) 144 | 145 | self.retranslateUi(MainWindow) 146 | self.speedCombox.setCurrentIndex(20) 147 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 148 | 149 | def retranslateUi(self, MainWindow): 150 | _translate = QtCore.QCoreApplication.translate 151 | MainWindow.setWindowTitle(_translate("MainWindow", "RTT转Telnet工具")) 152 | self.label.setText(_translate("MainWindow", "芯片型号:")) 153 | self.label_2.setText(_translate("MainWindow", "目标接口:")) 154 | self.interfaceCombox.setItemText(0, _translate("MainWindow", "SWD")) 155 | self.interfaceCombox.setItemText(1, _translate("MainWindow", "JTAG")) 156 | self.interfaceCombox.setItemText(2, _translate("MainWindow", "cJTAG")) 157 | self.interfaceCombox.setItemText(3, _translate("MainWindow", "FINE")) 158 | self.label_3.setText(_translate("MainWindow", "速度:")) 159 | self.speedCombox.setItemText(0, _translate("MainWindow", "5kHz")) 160 | self.speedCombox.setItemText(1, _translate("MainWindow", "10kHz")) 161 | self.speedCombox.setItemText(2, _translate("MainWindow", "20kHz")) 162 | self.speedCombox.setItemText(3, _translate("MainWindow", "30kHz")) 163 | self.speedCombox.setItemText(4, _translate("MainWindow", "50kHz")) 164 | self.speedCombox.setItemText(5, _translate("MainWindow", "100kHz")) 165 | self.speedCombox.setItemText(6, _translate("MainWindow", "200kHz")) 166 | self.speedCombox.setItemText(7, _translate("MainWindow", "300kHz")) 167 | self.speedCombox.setItemText(8, _translate("MainWindow", "400kHz")) 168 | self.speedCombox.setItemText(9, _translate("MainWindow", "500kHz")) 169 | self.speedCombox.setItemText(10, _translate("MainWindow", "600kHz")) 170 | self.speedCombox.setItemText(11, _translate("MainWindow", "650kHz")) 171 | self.speedCombox.setItemText(12, _translate("MainWindow", "750kHz")) 172 | self.speedCombox.setItemText(13, _translate("MainWindow", "900kHz")) 173 | self.speedCombox.setItemText(14, _translate("MainWindow", "1000kHz")) 174 | self.speedCombox.setItemText(15, _translate("MainWindow", "1334kHz")) 175 | self.speedCombox.setItemText(16, _translate("MainWindow", "1600kHz")) 176 | self.speedCombox.setItemText(17, _translate("MainWindow", "2000kHz")) 177 | self.speedCombox.setItemText(18, _translate("MainWindow", "2667kHz")) 178 | self.speedCombox.setItemText(19, _translate("MainWindow", "3200kHz")) 179 | self.speedCombox.setItemText(20, _translate("MainWindow", "4000kHz")) 180 | self.speedCombox.setItemText(21, _translate("MainWindow", "4800kHz")) 181 | self.speedCombox.setItemText(22, _translate("MainWindow", "5334kHz")) 182 | self.speedCombox.setItemText(23, _translate("MainWindow", "6000kHz")) 183 | self.speedCombox.setItemText(24, _translate("MainWindow", "8000kHz")) 184 | self.speedCombox.setItemText(25, _translate("MainWindow", "9600kHz")) 185 | self.speedCombox.setItemText(26, _translate("MainWindow", "12000kHz")) 186 | self.label_4.setText(_translate("MainWindow", "通道0对应端口号:")) 187 | self.channel0Port.setText(_translate("MainWindow", "6198")) 188 | self.label_5.setText(_translate("MainWindow", "通道1对应端口号:")) 189 | self.channel1Port.setText(_translate("MainWindow", "6199")) 190 | self.switchButton.setText(_translate("MainWindow", "开启")) 191 | self.hideButton.setText(_translate("MainWindow", "隐入托盘")) 192 | self.menu.setTitle(_translate("MainWindow", "作者")) 193 | self.menu_2.setTitle(_translate("MainWindow", "邮箱")) 194 | self.menu_3.setTitle(_translate("MainWindow", "姓名")) 195 | self.action619808090_qq_com.setText(_translate("MainWindow", "619808090@qq.com")) 196 | self.actionDriver.setText(_translate("MainWindow", "Driver")) 197 | -------------------------------------------------------------------------------- /seggerRtt代码包/SEGGER_RTT.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2019 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: 6.70a * 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: 17697 $ 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 | #ifndef BUFFER_SIZE_UP 89 | #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host 90 | #endif 91 | 92 | #ifndef BUFFER_SIZE_DOWN 93 | #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) 94 | #endif 95 | 96 | #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 97 | #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target 98 | #endif 99 | 100 | #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 101 | #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target 102 | #endif 103 | 104 | #ifndef SEGGER_RTT_BUFFER_SECTION 105 | #if defined(SEGGER_RTT_SECTION) 106 | #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION 107 | #endif 108 | #endif 109 | 110 | #ifndef SEGGER_RTT_ALIGNMENT 111 | #define SEGGER_RTT_ALIGNMENT 0 112 | #endif 113 | 114 | #ifndef SEGGER_RTT_BUFFER_ALIGNMENT 115 | #define SEGGER_RTT_BUFFER_ALIGNMENT 0 116 | #endif 117 | 118 | #ifndef SEGGER_RTT_MODE_DEFAULT 119 | #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP 120 | #endif 121 | 122 | #ifndef SEGGER_RTT_LOCK 123 | #define SEGGER_RTT_LOCK() 124 | #endif 125 | 126 | #ifndef SEGGER_RTT_UNLOCK 127 | #define SEGGER_RTT_UNLOCK() 128 | #endif 129 | 130 | #ifndef STRLEN 131 | #define STRLEN(a) strlen((a)) 132 | #endif 133 | 134 | #ifndef STRCPY 135 | #define STRCPY(pDest, pSrc, NumBytes) strcpy((pDest), (pSrc)) 136 | #endif 137 | 138 | #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP 139 | #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 140 | #endif 141 | 142 | #ifndef SEGGER_RTT_MEMCPY 143 | #ifdef MEMCPY 144 | #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) 145 | #else 146 | #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) 147 | #endif 148 | #endif 149 | 150 | #ifndef MIN 151 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 152 | #endif 153 | 154 | #ifndef MAX 155 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 156 | #endif 157 | // 158 | // For some environments, NULL may not be defined until certain headers are included 159 | // 160 | #ifndef NULL 161 | #define NULL 0 162 | #endif 163 | 164 | /********************************************************************* 165 | * 166 | * Defines, fixed 167 | * 168 | ********************************************************************** 169 | */ 170 | #if (defined __ICCARM__) || (defined __ICCRX__) 171 | #define RTT_PRAGMA(P) _Pragma(#P) 172 | #endif 173 | 174 | #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT 175 | #if (defined __GNUC__) 176 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 177 | #elif (defined __ICCARM__) || (defined __ICCRX__) 178 | #define PRAGMA(A) _Pragma(#A) 179 | #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ 180 | Var 181 | #elif (defined __CC_ARM) 182 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 183 | #else 184 | #error "Alignment not supported for this compiler." 185 | #endif 186 | #else 187 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var 188 | #endif 189 | 190 | #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) 191 | #if (defined __GNUC__) 192 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var 193 | #elif (defined __ICCARM__) || (defined __ICCRX__) 194 | #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ 195 | Var 196 | #elif (defined __CC_ARM) 197 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var 198 | #else 199 | #error "Section placement not supported for this compiler." 200 | #endif 201 | #else 202 | #define SEGGER_RTT_PUT_SECTION(Var, Section) Var 203 | #endif 204 | 205 | 206 | #if SEGGER_RTT_ALIGNMENT 207 | #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) 208 | #else 209 | #define SEGGER_RTT_CB_ALIGN(Var) Var 210 | #endif 211 | 212 | #if SEGGER_RTT_BUFFER_ALIGNMENT 213 | #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) 214 | #else 215 | #define SEGGER_RTT_BUFFER_ALIGN(Var) Var 216 | #endif 217 | 218 | 219 | #if defined(SEGGER_RTT_SECTION) 220 | #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) 221 | #else 222 | #define SEGGER_RTT_PUT_CB_SECTION(Var) Var 223 | #endif 224 | 225 | #if defined(SEGGER_RTT_BUFFER_SECTION) 226 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) 227 | #else 228 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var 229 | #endif 230 | 231 | /********************************************************************* 232 | * 233 | * Static const data 234 | * 235 | ********************************************************************** 236 | */ 237 | 238 | static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 239 | 240 | /********************************************************************* 241 | * 242 | * Static data 243 | * 244 | ********************************************************************** 245 | */ 246 | // 247 | // RTT Control Block and allocate buffers for channel 0 248 | // 249 | SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); 250 | 251 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); 252 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); 253 | 254 | static unsigned char _ActiveTerminal; 255 | 256 | /********************************************************************* 257 | * 258 | * Static functions 259 | * 260 | ********************************************************************** 261 | */ 262 | 263 | /********************************************************************* 264 | * 265 | * _DoInit() 266 | * 267 | * Function description 268 | * Initializes the control block an buffers. 269 | * May only be called via INIT() to avoid overriding settings. 270 | * 271 | */ 272 | #define INIT() do { \ 273 | if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ 274 | } while (0) 275 | static void _DoInit(void) { 276 | SEGGER_RTT_CB* p; 277 | // 278 | // Initialize control block 279 | // 280 | p = &_SEGGER_RTT; 281 | p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; 282 | p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; 283 | // 284 | // Initialize up buffer 0 285 | // 286 | p->aUp[0].sName = "Terminal"; 287 | p->aUp[0].pBuffer = _acUpBuffer; 288 | p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); 289 | p->aUp[0].RdOff = 0u; 290 | p->aUp[0].WrOff = 0u; 291 | p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; 292 | // 293 | // Initialize down buffer 0 294 | // 295 | p->aDown[0].sName = "Terminal"; 296 | p->aDown[0].pBuffer = _acDownBuffer; 297 | p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); 298 | p->aDown[0].RdOff = 0u; 299 | p->aDown[0].WrOff = 0u; 300 | p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; 301 | // 302 | // Finish initialization of the control block. 303 | // Copy Id string in three steps to make sure "SEGGER RTT" is not found 304 | // in initializer memory (usually flash) by J-Link 305 | // 306 | STRCPY(&p->acID[7], "RTT", 9); 307 | STRCPY(&p->acID[0], "SEGGER", 7); 308 | p->acID[6] = ' '; 309 | } 310 | 311 | /********************************************************************* 312 | * 313 | * _WriteBlocking() 314 | * 315 | * Function description 316 | * Stores a specified number of characters in SEGGER RTT ring buffer 317 | * and updates the associated write pointer which is periodically 318 | * read by the host. 319 | * The caller is responsible for managing the write chunk sizes as 320 | * _WriteBlocking() will block until all data has been posted successfully. 321 | * 322 | * Parameters 323 | * pRing Ring buffer to post to. 324 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 325 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 326 | * 327 | * Return value 328 | * >= 0 - Number of bytes written into buffer. 329 | */ 330 | static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { 331 | unsigned NumBytesToWrite; 332 | unsigned NumBytesWritten; 333 | unsigned RdOff; 334 | unsigned WrOff; 335 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 336 | char* pDst; 337 | #endif 338 | // 339 | // Write data to buffer and handle wrap-around if necessary 340 | // 341 | NumBytesWritten = 0u; 342 | WrOff = pRing->WrOff; 343 | do { 344 | RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime 345 | if (RdOff > WrOff) { 346 | NumBytesToWrite = RdOff - WrOff - 1u; 347 | } else { 348 | NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); 349 | } 350 | NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around 351 | NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); 352 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 353 | pDst = pRing->pBuffer + WrOff; 354 | NumBytesWritten += NumBytesToWrite; 355 | NumBytes -= NumBytesToWrite; 356 | WrOff += NumBytesToWrite; 357 | while (NumBytesToWrite--) { 358 | *pDst++ = *pBuffer++; 359 | }; 360 | #else 361 | SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); 362 | NumBytesWritten += NumBytesToWrite; 363 | pBuffer += NumBytesToWrite; 364 | NumBytes -= NumBytesToWrite; 365 | WrOff += NumBytesToWrite; 366 | #endif 367 | if (WrOff == pRing->SizeOfBuffer) { 368 | WrOff = 0u; 369 | } 370 | pRing->WrOff = WrOff; 371 | } while (NumBytes); 372 | // 373 | return NumBytesWritten; 374 | } 375 | 376 | /********************************************************************* 377 | * 378 | * _WriteNoCheck() 379 | * 380 | * Function description 381 | * Stores a specified number of characters in SEGGER RTT ring buffer 382 | * and updates the associated write pointer which is periodically 383 | * read by the host. 384 | * It is callers responsibility to make sure data actually fits in buffer. 385 | * 386 | * Parameters 387 | * pRing Ring buffer to post to. 388 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 389 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 390 | * 391 | * Notes 392 | * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking 393 | */ 394 | static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { 395 | unsigned NumBytesAtOnce; 396 | unsigned WrOff; 397 | unsigned Rem; 398 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 399 | char* pDst; 400 | #endif 401 | 402 | WrOff = pRing->WrOff; 403 | Rem = pRing->SizeOfBuffer - WrOff; 404 | if (Rem > NumBytes) { 405 | // 406 | // All data fits before wrap around 407 | // 408 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 409 | pDst = pRing->pBuffer + WrOff; 410 | WrOff += NumBytes; 411 | while (NumBytes--) { 412 | *pDst++ = *pData++; 413 | }; 414 | pRing->WrOff = WrOff; 415 | #else 416 | SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); 417 | pRing->WrOff = WrOff + NumBytes; 418 | #endif 419 | } else { 420 | // 421 | // We reach the end of the buffer, so need to wrap around 422 | // 423 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 424 | pDst = pRing->pBuffer + WrOff; 425 | NumBytesAtOnce = Rem; 426 | while (NumBytesAtOnce--) { 427 | *pDst++ = *pData++; 428 | }; 429 | pDst = pRing->pBuffer; 430 | NumBytesAtOnce = NumBytes - Rem; 431 | while (NumBytesAtOnce--) { 432 | *pDst++ = *pData++; 433 | }; 434 | pRing->WrOff = NumBytes - Rem; 435 | #else 436 | NumBytesAtOnce = Rem; 437 | SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); 438 | NumBytesAtOnce = NumBytes - Rem; 439 | SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce); 440 | pRing->WrOff = NumBytesAtOnce; 441 | #endif 442 | } 443 | } 444 | 445 | /********************************************************************* 446 | * 447 | * _PostTerminalSwitch() 448 | * 449 | * Function description 450 | * Switch terminal to the given terminal ID. It is the caller's 451 | * responsibility to ensure the terminal ID is correct and there is 452 | * enough space in the buffer for this to complete successfully. 453 | * 454 | * Parameters 455 | * pRing Ring buffer to post to. 456 | * TerminalId Terminal ID to switch to. 457 | */ 458 | static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { 459 | unsigned char ac[2]; 460 | 461 | ac[0] = 0xFFu; 462 | ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit 463 | _WriteBlocking(pRing, (const char*)ac, 2u); 464 | } 465 | 466 | /********************************************************************* 467 | * 468 | * _GetAvailWriteSpace() 469 | * 470 | * Function description 471 | * Returns the number of bytes that can be written to the ring 472 | * buffer without blocking. 473 | * 474 | * Parameters 475 | * pRing Ring buffer to check. 476 | * 477 | * Return value 478 | * Number of bytes that are free in the buffer. 479 | */ 480 | static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { 481 | unsigned RdOff; 482 | unsigned WrOff; 483 | unsigned r; 484 | // 485 | // Avoid warnings regarding volatile access order. It's not a problem 486 | // in this case, but dampen compiler enthusiasm. 487 | // 488 | RdOff = pRing->RdOff; 489 | WrOff = pRing->WrOff; 490 | if (RdOff <= WrOff) { 491 | r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; 492 | } else { 493 | r = RdOff - WrOff - 1u; 494 | } 495 | return r; 496 | } 497 | 498 | /********************************************************************* 499 | * 500 | * Public code 501 | * 502 | ********************************************************************** 503 | */ 504 | /********************************************************************* 505 | * 506 | * SEGGER_RTT_ReadUpBufferNoLock() 507 | * 508 | * Function description 509 | * Reads characters from SEGGER real-time-terminal control block 510 | * which have been previously stored by the application. 511 | * Do not lock against interrupts and multiple access. 512 | * Used to do the same operation that J-Link does, to transfer 513 | * RTT data via other channels, such as TCP/IP or UART. 514 | * 515 | * Parameters 516 | * BufferIndex Index of Up-buffer to be used. 517 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 518 | * BufferSize Size of the target application buffer. 519 | * 520 | * Return value 521 | * Number of bytes that have been read. 522 | * 523 | * Additional information 524 | * This function must not be called when J-Link might also do RTT. 525 | */ 526 | unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 527 | unsigned NumBytesRem; 528 | unsigned NumBytesRead; 529 | unsigned RdOff; 530 | unsigned WrOff; 531 | unsigned char* pBuffer; 532 | SEGGER_RTT_BUFFER_UP* pRing; 533 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 534 | const char* pSrc; 535 | #endif 536 | // 537 | INIT(); 538 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 539 | pBuffer = (unsigned char*)pData; 540 | RdOff = pRing->RdOff; 541 | WrOff = pRing->WrOff; 542 | NumBytesRead = 0u; 543 | // 544 | // Read from current read position to wrap-around of buffer, first 545 | // 546 | if (RdOff > WrOff) { 547 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 548 | NumBytesRem = MIN(NumBytesRem, BufferSize); 549 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 550 | pSrc = pRing->pBuffer + RdOff; 551 | NumBytesRead += NumBytesRem; 552 | BufferSize -= NumBytesRem; 553 | RdOff += NumBytesRem; 554 | while (NumBytesRem--) { 555 | *pBuffer++ = *pSrc++; 556 | }; 557 | #else 558 | SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); 559 | NumBytesRead += NumBytesRem; 560 | pBuffer += NumBytesRem; 561 | BufferSize -= NumBytesRem; 562 | RdOff += NumBytesRem; 563 | #endif 564 | // 565 | // Handle wrap-around of buffer 566 | // 567 | if (RdOff == pRing->SizeOfBuffer) { 568 | RdOff = 0u; 569 | } 570 | } 571 | // 572 | // Read remaining items of buffer 573 | // 574 | NumBytesRem = WrOff - RdOff; 575 | NumBytesRem = MIN(NumBytesRem, BufferSize); 576 | if (NumBytesRem > 0u) { 577 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 578 | pSrc = pRing->pBuffer + RdOff; 579 | NumBytesRead += NumBytesRem; 580 | BufferSize -= NumBytesRem; 581 | RdOff += NumBytesRem; 582 | while (NumBytesRem--) { 583 | *pBuffer++ = *pSrc++; 584 | }; 585 | #else 586 | SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); 587 | NumBytesRead += NumBytesRem; 588 | pBuffer += NumBytesRem; 589 | BufferSize -= NumBytesRem; 590 | RdOff += NumBytesRem; 591 | #endif 592 | } 593 | // 594 | // Update read offset of buffer 595 | // 596 | if (NumBytesRead) { 597 | pRing->RdOff = RdOff; 598 | } 599 | // 600 | return NumBytesRead; 601 | } 602 | 603 | /********************************************************************* 604 | * 605 | * SEGGER_RTT_ReadNoLock() 606 | * 607 | * Function description 608 | * Reads characters from SEGGER real-time-terminal control block 609 | * which have been previously stored by the host. 610 | * Do not lock against interrupts and multiple access. 611 | * 612 | * Parameters 613 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 614 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 615 | * BufferSize Size of the target application buffer. 616 | * 617 | * Return value 618 | * Number of bytes that have been read. 619 | */ 620 | unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 621 | unsigned NumBytesRem; 622 | unsigned NumBytesRead; 623 | unsigned RdOff; 624 | unsigned WrOff; 625 | unsigned char* pBuffer; 626 | SEGGER_RTT_BUFFER_DOWN* pRing; 627 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 628 | const char* pSrc; 629 | #endif 630 | // 631 | INIT(); 632 | pRing = &_SEGGER_RTT.aDown[BufferIndex]; 633 | pBuffer = (unsigned char*)pData; 634 | RdOff = pRing->RdOff; 635 | WrOff = pRing->WrOff; 636 | NumBytesRead = 0u; 637 | // 638 | // Read from current read position to wrap-around of buffer, first 639 | // 640 | if (RdOff > WrOff) { 641 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 642 | NumBytesRem = MIN(NumBytesRem, BufferSize); 643 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 644 | pSrc = pRing->pBuffer + RdOff; 645 | NumBytesRead += NumBytesRem; 646 | BufferSize -= NumBytesRem; 647 | RdOff += NumBytesRem; 648 | while (NumBytesRem--) { 649 | *pBuffer++ = *pSrc++; 650 | }; 651 | #else 652 | SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); 653 | NumBytesRead += NumBytesRem; 654 | pBuffer += NumBytesRem; 655 | BufferSize -= NumBytesRem; 656 | RdOff += NumBytesRem; 657 | #endif 658 | // 659 | // Handle wrap-around of buffer 660 | // 661 | if (RdOff == pRing->SizeOfBuffer) { 662 | RdOff = 0u; 663 | } 664 | } 665 | // 666 | // Read remaining items of buffer 667 | // 668 | NumBytesRem = WrOff - RdOff; 669 | NumBytesRem = MIN(NumBytesRem, BufferSize); 670 | if (NumBytesRem > 0u) { 671 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 672 | pSrc = pRing->pBuffer + RdOff; 673 | NumBytesRead += NumBytesRem; 674 | BufferSize -= NumBytesRem; 675 | RdOff += NumBytesRem; 676 | while (NumBytesRem--) { 677 | *pBuffer++ = *pSrc++; 678 | }; 679 | #else 680 | SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); 681 | NumBytesRead += NumBytesRem; 682 | pBuffer += NumBytesRem; 683 | BufferSize -= NumBytesRem; 684 | RdOff += NumBytesRem; 685 | #endif 686 | } 687 | if (NumBytesRead) { 688 | pRing->RdOff = RdOff; 689 | } 690 | // 691 | return NumBytesRead; 692 | } 693 | 694 | /********************************************************************* 695 | * 696 | * SEGGER_RTT_ReadUpBuffer 697 | * 698 | * Function description 699 | * Reads characters from SEGGER real-time-terminal control block 700 | * which have been previously stored by the application. 701 | * Used to do the same operation that J-Link does, to transfer 702 | * RTT data via other channels, such as TCP/IP or UART. 703 | * 704 | * Parameters 705 | * BufferIndex Index of Up-buffer to be used. 706 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 707 | * BufferSize Size of the target application buffer. 708 | * 709 | * Return value 710 | * Number of bytes that have been read. 711 | * 712 | * Additional information 713 | * This function must not be called when J-Link might also do RTT. 714 | * This function locks against all other RTT operations. I.e. during 715 | * the read operation, writing is also locked. 716 | * If only one consumer reads from the up buffer, 717 | * call sEGGER_RTT_ReadUpBufferNoLock() instead. 718 | */ 719 | unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 720 | unsigned NumBytesRead; 721 | // 722 | SEGGER_RTT_LOCK(); 723 | // 724 | // Call the non-locking read function 725 | // 726 | NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); 727 | // 728 | // Finish up. 729 | // 730 | SEGGER_RTT_UNLOCK(); 731 | // 732 | return NumBytesRead; 733 | } 734 | 735 | /********************************************************************* 736 | * 737 | * SEGGER_RTT_Read 738 | * 739 | * Function description 740 | * Reads characters from SEGGER real-time-terminal control block 741 | * which have been previously stored by the host. 742 | * 743 | * Parameters 744 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 745 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 746 | * BufferSize Size of the target application buffer. 747 | * 748 | * Return value 749 | * Number of bytes that have been read. 750 | */ 751 | unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 752 | unsigned NumBytesRead; 753 | // 754 | SEGGER_RTT_LOCK(); 755 | // 756 | // Call the non-locking read function 757 | // 758 | NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); 759 | // 760 | // Finish up. 761 | // 762 | SEGGER_RTT_UNLOCK(); 763 | // 764 | return NumBytesRead; 765 | } 766 | 767 | /********************************************************************* 768 | * 769 | * SEGGER_RTT_WriteWithOverwriteNoLock 770 | * 771 | * Function description 772 | * Stores a specified number of characters in SEGGER RTT 773 | * control block. 774 | * SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 775 | * and overwrites data if the data does not fit into the buffer. 776 | * 777 | * Parameters 778 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 779 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 780 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 781 | * 782 | * Notes 783 | * (1) If there is not enough space in the "Up"-buffer, data is overwritten. 784 | * (2) For performance reasons this function does not call Init() 785 | * and may only be called after RTT has been initialized. 786 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 787 | * (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 788 | * connection reads RTT data. 789 | */ 790 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 791 | const char* pData; 792 | SEGGER_RTT_BUFFER_UP* pRing; 793 | unsigned Avail; 794 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 795 | char* pDst; 796 | #endif 797 | 798 | pData = (const char *)pBuffer; 799 | // 800 | // Get "to-host" ring buffer and copy some elements into local variables. 801 | // 802 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 803 | // 804 | // Check if we will overwrite data and need to adjust the RdOff. 805 | // 806 | if (pRing->WrOff == pRing->RdOff) { 807 | Avail = pRing->SizeOfBuffer - 1u; 808 | } else if ( pRing->WrOff < pRing->RdOff) { 809 | Avail = pRing->RdOff - pRing->WrOff - 1u; 810 | } else { 811 | Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; 812 | } 813 | if (NumBytes > Avail) { 814 | pRing->RdOff += (NumBytes - Avail); 815 | while (pRing->RdOff >= pRing->SizeOfBuffer) { 816 | pRing->RdOff -= pRing->SizeOfBuffer; 817 | } 818 | } 819 | // 820 | // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds 821 | // 822 | Avail = pRing->SizeOfBuffer - pRing->WrOff; 823 | do { 824 | if (Avail > NumBytes) { 825 | // 826 | // Last round 827 | // 828 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 829 | pDst = pRing->pBuffer + pRing->WrOff; 830 | Avail = NumBytes; 831 | while (NumBytes--) { 832 | *pDst++ = *pData++; 833 | }; 834 | pRing->WrOff += Avail; 835 | #else 836 | SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes); 837 | pRing->WrOff += NumBytes; 838 | #endif 839 | break; 840 | } else { 841 | // 842 | // Wrap-around necessary, write until wrap-around and reset WrOff 843 | // 844 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 845 | pDst = pRing->pBuffer + pRing->WrOff; 846 | NumBytes -= Avail; 847 | while (Avail--) { 848 | *pDst++ = *pData++; 849 | }; 850 | pRing->WrOff = 0; 851 | #else 852 | SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail); 853 | pData += Avail; 854 | pRing->WrOff = 0; 855 | NumBytes -= Avail; 856 | #endif 857 | Avail = (pRing->SizeOfBuffer - 1); 858 | } 859 | } while (NumBytes); 860 | } 861 | 862 | /********************************************************************* 863 | * 864 | * SEGGER_RTT_WriteSkipNoLock 865 | * 866 | * Function description 867 | * Stores a specified number of characters in SEGGER RTT 868 | * control block which is then read by the host. 869 | * SEGGER_RTT_WriteSkipNoLock does not lock the application and 870 | * skips all data, if the data does not fit into the buffer. 871 | * 872 | * Parameters 873 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 874 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 875 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 876 | * MUST be > 0!!! 877 | * This is done for performance reasons, so no initial check has do be done. 878 | * 879 | * Return value 880 | * 1: Data has been copied 881 | * 0: No space, data has not been copied 882 | * 883 | * Notes 884 | * (1) If there is not enough space in the "Up"-buffer, all data is dropped. 885 | * (2) For performance reasons this function does not call Init() 886 | * and may only be called after RTT has been initialized. 887 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 888 | */ 889 | #if (RTT_USE_ASM == 0) 890 | unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 891 | const char* pData; 892 | SEGGER_RTT_BUFFER_UP* pRing; 893 | unsigned Avail; 894 | unsigned RdOff; 895 | unsigned WrOff; 896 | unsigned Rem; 897 | // 898 | // Cases: 899 | // 1) RdOff <= WrOff => Space until wrap-around is sufficient 900 | // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) 901 | // 3) RdOff < WrOff => No space in buf 902 | // 4) RdOff > WrOff => Space is sufficient 903 | // 5) RdOff > WrOff => No space in buf 904 | // 905 | // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough 906 | // 907 | pData = (const char *)pBuffer; 908 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 909 | RdOff = pRing->RdOff; 910 | WrOff = pRing->WrOff; 911 | if (RdOff <= WrOff) { // Case 1), 2) or 3) 912 | Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) 913 | if (Avail >= NumBytes) { // Case 1)? 914 | CopyStraight: 915 | memcpy(pRing->pBuffer + WrOff, pData, NumBytes); 916 | pRing->WrOff = WrOff + NumBytes; 917 | return 1; 918 | } 919 | Avail += RdOff; // Space incl. wrap-around 920 | if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) 921 | Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer 922 | memcpy(pRing->pBuffer + WrOff, pData, Rem); // Copy 1st chunk 923 | NumBytes -= Rem; 924 | // 925 | // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used 926 | // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element 927 | // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks 928 | // Therefore, check if 2nd memcpy is necessary at all 929 | // 930 | if (NumBytes) { 931 | memcpy(pRing->pBuffer, pData + Rem, NumBytes); 932 | } 933 | pRing->WrOff = NumBytes; 934 | return 1; 935 | } 936 | } else { // Potential case 4) 937 | Avail = RdOff - WrOff - 1u; 938 | if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit) 939 | goto CopyStraight; 940 | } 941 | } 942 | return 0; // No space in buffer 943 | } 944 | #endif 945 | 946 | /********************************************************************* 947 | * 948 | * SEGGER_RTT_WriteDownBufferNoLock 949 | * 950 | * Function description 951 | * Stores a specified number of characters in SEGGER RTT 952 | * control block inside a buffer. 953 | * SEGGER_RTT_WriteDownBufferNoLock does not lock the application. 954 | * Used to do the same operation that J-Link does, to transfer 955 | * RTT data from other channels, such as TCP/IP or UART. 956 | * 957 | * Parameters 958 | * BufferIndex Index of "Down"-buffer to be used. 959 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 960 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 961 | * 962 | * Return value 963 | * Number of bytes which have been stored in the "Down"-buffer. 964 | * 965 | * Notes 966 | * (1) Data is stored according to buffer flags. 967 | * (2) For performance reasons this function does not call Init() 968 | * and may only be called after RTT has been initialized. 969 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 970 | * 971 | * Additional information 972 | * This function must not be called when J-Link might also do RTT. 973 | */ 974 | unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 975 | unsigned Status; 976 | unsigned Avail; 977 | const char* pData; 978 | SEGGER_RTT_BUFFER_UP* pRing; 979 | 980 | pData = (const char *)pBuffer; 981 | // 982 | // Get "to-target" ring buffer. 983 | // 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. 984 | // 985 | pRing = (SEGGER_RTT_BUFFER_UP*)&_SEGGER_RTT.aDown[BufferIndex]; 986 | // 987 | // How we output depends upon the mode... 988 | // 989 | switch (pRing->Flags) { 990 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 991 | // 992 | // If we are in skip mode and there is no space for the whole 993 | // of this output, don't bother. 994 | // 995 | Avail = _GetAvailWriteSpace(pRing); 996 | if (Avail < NumBytes) { 997 | Status = 0u; 998 | } else { 999 | Status = NumBytes; 1000 | _WriteNoCheck(pRing, pData, NumBytes); 1001 | } 1002 | break; 1003 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1004 | // 1005 | // If we are in trim mode, trim to what we can output without blocking. 1006 | // 1007 | Avail = _GetAvailWriteSpace(pRing); 1008 | Status = Avail < NumBytes ? Avail : NumBytes; 1009 | _WriteNoCheck(pRing, pData, Status); 1010 | break; 1011 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1012 | // 1013 | // If we are in blocking mode, output everything. 1014 | // 1015 | Status = _WriteBlocking(pRing, pData, NumBytes); 1016 | break; 1017 | default: 1018 | Status = 0u; 1019 | break; 1020 | } 1021 | // 1022 | // Finish up. 1023 | // 1024 | return Status; 1025 | } 1026 | 1027 | /********************************************************************* 1028 | * 1029 | * SEGGER_RTT_WriteNoLock 1030 | * 1031 | * Function description 1032 | * Stores a specified number of characters in SEGGER RTT 1033 | * control block which is then read by the host. 1034 | * SEGGER_RTT_WriteNoLock does not lock the application. 1035 | * 1036 | * Parameters 1037 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1038 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1039 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1040 | * 1041 | * Return value 1042 | * Number of bytes which have been stored in the "Up"-buffer. 1043 | * 1044 | * Notes 1045 | * (1) Data is stored according to buffer flags. 1046 | * (2) For performance reasons this function does not call Init() 1047 | * and may only be called after RTT has been initialized. 1048 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1049 | */ 1050 | unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1051 | unsigned Status; 1052 | unsigned Avail; 1053 | const char* pData; 1054 | SEGGER_RTT_BUFFER_UP* pRing; 1055 | 1056 | pData = (const char *)pBuffer; 1057 | // 1058 | // Get "to-host" ring buffer. 1059 | // 1060 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1061 | // 1062 | // How we output depends upon the mode... 1063 | // 1064 | switch (pRing->Flags) { 1065 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1066 | // 1067 | // If we are in skip mode and there is no space for the whole 1068 | // of this output, don't bother. 1069 | // 1070 | Avail = _GetAvailWriteSpace(pRing); 1071 | if (Avail < NumBytes) { 1072 | Status = 0u; 1073 | } else { 1074 | Status = NumBytes; 1075 | _WriteNoCheck(pRing, pData, NumBytes); 1076 | } 1077 | break; 1078 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1079 | // 1080 | // If we are in trim mode, trim to what we can output without blocking. 1081 | // 1082 | Avail = _GetAvailWriteSpace(pRing); 1083 | Status = Avail < NumBytes ? Avail : NumBytes; 1084 | _WriteNoCheck(pRing, pData, Status); 1085 | break; 1086 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1087 | // 1088 | // If we are in blocking mode, output everything. 1089 | // 1090 | Status = _WriteBlocking(pRing, pData, NumBytes); 1091 | break; 1092 | default: 1093 | Status = 0u; 1094 | break; 1095 | } 1096 | // 1097 | // Finish up. 1098 | // 1099 | return Status; 1100 | } 1101 | 1102 | /********************************************************************* 1103 | * 1104 | * SEGGER_RTT_WriteDownBuffer 1105 | * 1106 | * Function description 1107 | * Stores a specified number of characters in SEGGER RTT control block in a buffer. 1108 | * 1109 | * Parameters 1110 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1111 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1112 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1113 | * 1114 | * Return value 1115 | * Number of bytes which have been stored in the "Down"-buffer. 1116 | * 1117 | * Notes 1118 | * (1) Data is stored according to buffer flags. 1119 | * 1120 | * Additional information 1121 | * This function must not be called when J-Link might also do RTT. 1122 | * This function locks against all other RTT operations. I.e. during 1123 | * the write operation, writing from the application is also locked. 1124 | * If only one consumer writes to the down buffer, 1125 | * call SEGGER_RTT_WriteDownBufferNoLock() instead. 1126 | */ 1127 | unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1128 | unsigned Status; 1129 | // 1130 | INIT(); 1131 | SEGGER_RTT_LOCK(); 1132 | // 1133 | // Call the non-locking write function 1134 | // 1135 | Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); 1136 | // 1137 | // Finish up. 1138 | // 1139 | SEGGER_RTT_UNLOCK(); 1140 | // 1141 | return Status; 1142 | } 1143 | 1144 | /********************************************************************* 1145 | * 1146 | * SEGGER_RTT_Write 1147 | * 1148 | * Function description 1149 | * Stores a specified number of characters in SEGGER RTT 1150 | * control block which is then read by the host. 1151 | * 1152 | * Parameters 1153 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1154 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1155 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1156 | * 1157 | * Return value 1158 | * Number of bytes which have been stored in the "Up"-buffer. 1159 | * 1160 | * Notes 1161 | * (1) Data is stored according to buffer flags. 1162 | */ 1163 | unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1164 | unsigned Status; 1165 | // 1166 | INIT(); 1167 | SEGGER_RTT_LOCK(); 1168 | // 1169 | // Call the non-locking write function 1170 | // 1171 | Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); 1172 | // 1173 | // Finish up. 1174 | // 1175 | SEGGER_RTT_UNLOCK(); 1176 | // 1177 | return Status; 1178 | } 1179 | 1180 | /********************************************************************* 1181 | * 1182 | * SEGGER_RTT_WriteString 1183 | * 1184 | * Function description 1185 | * Stores string in SEGGER RTT control block. 1186 | * This data is read by the host. 1187 | * 1188 | * Parameters 1189 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1190 | * s Pointer to string. 1191 | * 1192 | * Return value 1193 | * Number of bytes which have been stored in the "Up"-buffer. 1194 | * 1195 | * Notes 1196 | * (1) Data is stored according to buffer flags. 1197 | * (2) String passed to this function has to be \0 terminated 1198 | * (3) \0 termination character is *not* stored in RTT buffer 1199 | */ 1200 | unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { 1201 | unsigned Len; 1202 | 1203 | Len = STRLEN(s); 1204 | return SEGGER_RTT_Write(BufferIndex, s, Len); 1205 | } 1206 | 1207 | /********************************************************************* 1208 | * 1209 | * SEGGER_RTT_PutCharSkipNoLock 1210 | * 1211 | * Function description 1212 | * Stores a single character/byte in SEGGER RTT buffer. 1213 | * SEGGER_RTT_PutCharSkipNoLock does not lock the application and 1214 | * skips the byte, if it does not fit into the buffer. 1215 | * 1216 | * Parameters 1217 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1218 | * c Byte to be stored. 1219 | * 1220 | * Return value 1221 | * Number of bytes which have been stored in the "Up"-buffer. 1222 | * 1223 | * Notes 1224 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1225 | * (2) For performance reasons this function does not call Init() 1226 | * and may only be called after RTT has been initialized. 1227 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1228 | */ 1229 | 1230 | unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { 1231 | SEGGER_RTT_BUFFER_UP* pRing; 1232 | unsigned WrOff; 1233 | unsigned Status; 1234 | // 1235 | // Get "to-host" ring buffer. 1236 | // 1237 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1238 | // 1239 | // Get write position and handle wrap-around if necessary 1240 | // 1241 | WrOff = pRing->WrOff + 1; 1242 | if (WrOff == pRing->SizeOfBuffer) { 1243 | WrOff = 0; 1244 | } 1245 | // 1246 | // Output byte if free space is available 1247 | // 1248 | if (WrOff != pRing->RdOff) { 1249 | pRing->pBuffer[pRing->WrOff] = c; 1250 | pRing->WrOff = WrOff; 1251 | Status = 1; 1252 | } else { 1253 | Status = 0; 1254 | } 1255 | // 1256 | return Status; 1257 | } 1258 | 1259 | /********************************************************************* 1260 | * 1261 | * SEGGER_RTT_PutCharSkip 1262 | * 1263 | * Function description 1264 | * Stores a single character/byte in SEGGER RTT buffer. 1265 | * 1266 | * Parameters 1267 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1268 | * c Byte to be stored. 1269 | * 1270 | * Return value 1271 | * Number of bytes which have been stored in the "Up"-buffer. 1272 | * 1273 | * Notes 1274 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1275 | */ 1276 | 1277 | unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { 1278 | SEGGER_RTT_BUFFER_UP* pRing; 1279 | unsigned WrOff; 1280 | unsigned Status; 1281 | // 1282 | // Prepare 1283 | // 1284 | INIT(); 1285 | SEGGER_RTT_LOCK(); 1286 | // 1287 | // Get "to-host" ring buffer. 1288 | // 1289 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1290 | // 1291 | // Get write position and handle wrap-around if necessary 1292 | // 1293 | WrOff = pRing->WrOff + 1; 1294 | if (WrOff == pRing->SizeOfBuffer) { 1295 | WrOff = 0; 1296 | } 1297 | // 1298 | // Output byte if free space is available 1299 | // 1300 | if (WrOff != pRing->RdOff) { 1301 | pRing->pBuffer[pRing->WrOff] = c; 1302 | pRing->WrOff = WrOff; 1303 | Status = 1; 1304 | } else { 1305 | Status = 0; 1306 | } 1307 | // 1308 | // Finish up. 1309 | // 1310 | SEGGER_RTT_UNLOCK(); 1311 | // 1312 | return Status; 1313 | } 1314 | 1315 | /********************************************************************* 1316 | * 1317 | * SEGGER_RTT_PutChar 1318 | * 1319 | * Function description 1320 | * Stores a single character/byte in SEGGER RTT buffer. 1321 | * 1322 | * Parameters 1323 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1324 | * c Byte to be stored. 1325 | * 1326 | * Return value 1327 | * Number of bytes which have been stored in the "Up"-buffer. 1328 | * 1329 | * Notes 1330 | * (1) Data is stored according to buffer flags. 1331 | */ 1332 | 1333 | unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { 1334 | SEGGER_RTT_BUFFER_UP* pRing; 1335 | unsigned WrOff; 1336 | unsigned Status; 1337 | // 1338 | // Prepare 1339 | // 1340 | INIT(); 1341 | SEGGER_RTT_LOCK(); 1342 | // 1343 | // Get "to-host" ring buffer. 1344 | // 1345 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1346 | // 1347 | // Get write position and handle wrap-around if necessary 1348 | // 1349 | WrOff = pRing->WrOff + 1; 1350 | if (WrOff == pRing->SizeOfBuffer) { 1351 | WrOff = 0; 1352 | } 1353 | // 1354 | // Wait for free space if mode is set to blocking 1355 | // 1356 | if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1357 | while (WrOff == pRing->RdOff) { 1358 | ; 1359 | } 1360 | } 1361 | // 1362 | // Output byte if free space is available 1363 | // 1364 | if (WrOff != pRing->RdOff) { 1365 | pRing->pBuffer[pRing->WrOff] = c; 1366 | pRing->WrOff = WrOff; 1367 | Status = 1; 1368 | } else { 1369 | Status = 0; 1370 | } 1371 | // 1372 | // Finish up. 1373 | // 1374 | SEGGER_RTT_UNLOCK(); 1375 | // 1376 | return Status; 1377 | } 1378 | 1379 | /********************************************************************* 1380 | * 1381 | * SEGGER_RTT_GetKey 1382 | * 1383 | * Function description 1384 | * Reads one character from the SEGGER RTT buffer. 1385 | * Host has previously stored data there. 1386 | * 1387 | * Return value 1388 | * < 0 - No character available (buffer empty). 1389 | * >= 0 - Character which has been read. (Possible values: 0 - 255) 1390 | * 1391 | * Notes 1392 | * (1) This function is only specified for accesses to RTT buffer 0. 1393 | */ 1394 | int SEGGER_RTT_GetKey(void) { 1395 | char c; 1396 | int r; 1397 | 1398 | r = (int)SEGGER_RTT_Read(0u, &c, 1u); 1399 | if (r == 1) { 1400 | r = (int)(unsigned char)c; 1401 | } else { 1402 | r = -1; 1403 | } 1404 | return r; 1405 | } 1406 | 1407 | /********************************************************************* 1408 | * 1409 | * SEGGER_RTT_WaitKey 1410 | * 1411 | * Function description 1412 | * Waits until at least one character is avaible in the SEGGER RTT buffer. 1413 | * Once a character is available, it is read and this function returns. 1414 | * 1415 | * Return value 1416 | * >=0 - Character which has been read. 1417 | * 1418 | * Notes 1419 | * (1) This function is only specified for accesses to RTT buffer 0 1420 | * (2) This function is blocking if no character is present in RTT buffer 1421 | */ 1422 | int SEGGER_RTT_WaitKey(void) { 1423 | int r; 1424 | 1425 | do { 1426 | r = SEGGER_RTT_GetKey(); 1427 | } while (r < 0); 1428 | return r; 1429 | } 1430 | 1431 | /********************************************************************* 1432 | * 1433 | * SEGGER_RTT_HasKey 1434 | * 1435 | * Function description 1436 | * Checks if at least one character for reading is available in the SEGGER RTT buffer. 1437 | * 1438 | * Return value 1439 | * == 0 - No characters are available to read. 1440 | * == 1 - At least one character is available. 1441 | * 1442 | * Notes 1443 | * (1) This function is only specified for accesses to RTT buffer 0 1444 | */ 1445 | int SEGGER_RTT_HasKey(void) { 1446 | unsigned RdOff; 1447 | int r; 1448 | 1449 | INIT(); 1450 | RdOff = _SEGGER_RTT.aDown[0].RdOff; 1451 | if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { 1452 | r = 1; 1453 | } else { 1454 | r = 0; 1455 | } 1456 | return r; 1457 | } 1458 | 1459 | /********************************************************************* 1460 | * 1461 | * SEGGER_RTT_HasData 1462 | * 1463 | * Function description 1464 | * Check if there is data from the host in the given buffer. 1465 | * 1466 | * Return value: 1467 | * ==0: No data 1468 | * !=0: Data in buffer 1469 | * 1470 | */ 1471 | unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { 1472 | SEGGER_RTT_BUFFER_DOWN* pRing; 1473 | unsigned v; 1474 | 1475 | pRing = &_SEGGER_RTT.aDown[BufferIndex]; 1476 | v = pRing->WrOff; 1477 | return v - pRing->RdOff; 1478 | } 1479 | 1480 | /********************************************************************* 1481 | * 1482 | * SEGGER_RTT_HasDataUp 1483 | * 1484 | * Function description 1485 | * Check if there is data remaining to be sent in the given buffer. 1486 | * 1487 | * Return value: 1488 | * ==0: No data 1489 | * !=0: Data in buffer 1490 | * 1491 | */ 1492 | unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { 1493 | SEGGER_RTT_BUFFER_UP* pRing; 1494 | unsigned v; 1495 | 1496 | pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1497 | v = pRing->RdOff; 1498 | return pRing->WrOff - v; 1499 | } 1500 | 1501 | /********************************************************************* 1502 | * 1503 | * SEGGER_RTT_AllocDownBuffer 1504 | * 1505 | * Function description 1506 | * Run-time configuration of the next down-buffer (H->T). 1507 | * The next buffer, which is not used yet is configured. 1508 | * This includes: Buffer address, size, name, flags, ... 1509 | * 1510 | * Parameters 1511 | * sName Pointer to a constant name string. 1512 | * pBuffer Pointer to a buffer to be used. 1513 | * BufferSize Size of the buffer. 1514 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1515 | * 1516 | * Return value 1517 | * >= 0 - O.K. Buffer Index 1518 | * < 0 - Error 1519 | */ 1520 | int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1521 | int BufferIndex; 1522 | 1523 | INIT(); 1524 | SEGGER_RTT_LOCK(); 1525 | BufferIndex = 0; 1526 | do { 1527 | if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { 1528 | break; 1529 | } 1530 | BufferIndex++; 1531 | } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); 1532 | if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { 1533 | _SEGGER_RTT.aDown[BufferIndex].sName = sName; 1534 | _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; 1535 | _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; 1536 | _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; 1537 | _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; 1538 | _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; 1539 | } else { 1540 | BufferIndex = -1; 1541 | } 1542 | SEGGER_RTT_UNLOCK(); 1543 | return BufferIndex; 1544 | } 1545 | 1546 | /********************************************************************* 1547 | * 1548 | * SEGGER_RTT_AllocUpBuffer 1549 | * 1550 | * Function description 1551 | * Run-time configuration of the next up-buffer (T->H). 1552 | * The next buffer, which is not used yet is configured. 1553 | * This includes: Buffer address, size, name, flags, ... 1554 | * 1555 | * Parameters 1556 | * sName Pointer to a constant name string. 1557 | * pBuffer Pointer to a buffer to be used. 1558 | * BufferSize Size of the buffer. 1559 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1560 | * 1561 | * Return value 1562 | * >= 0 - O.K. Buffer Index 1563 | * < 0 - Error 1564 | */ 1565 | int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1566 | int BufferIndex; 1567 | 1568 | INIT(); 1569 | SEGGER_RTT_LOCK(); 1570 | BufferIndex = 0; 1571 | do { 1572 | if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { 1573 | break; 1574 | } 1575 | BufferIndex++; 1576 | } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); 1577 | if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { 1578 | _SEGGER_RTT.aUp[BufferIndex].sName = sName; 1579 | _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; 1580 | _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; 1581 | _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; 1582 | _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; 1583 | _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; 1584 | } else { 1585 | BufferIndex = -1; 1586 | } 1587 | SEGGER_RTT_UNLOCK(); 1588 | return BufferIndex; 1589 | } 1590 | 1591 | /********************************************************************* 1592 | * 1593 | * SEGGER_RTT_ConfigUpBuffer 1594 | * 1595 | * Function description 1596 | * Run-time configuration of a specific up-buffer (T->H). 1597 | * Buffer to be configured is specified by index. 1598 | * This includes: Buffer address, size, name, flags, ... 1599 | * 1600 | * Parameters 1601 | * BufferIndex Index of the buffer to configure. 1602 | * sName Pointer to a constant name string. 1603 | * pBuffer Pointer to a buffer to be used. 1604 | * BufferSize Size of the buffer. 1605 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1606 | * 1607 | * Return value 1608 | * >= 0 - O.K. 1609 | * < 0 - Error 1610 | * 1611 | * Additional information 1612 | * Buffer 0 is configured on compile-time. 1613 | * May only be called once per buffer. 1614 | * Buffer name and flags can be reconfigured using the appropriate functions. 1615 | */ 1616 | int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1617 | int r; 1618 | 1619 | INIT(); 1620 | if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { 1621 | SEGGER_RTT_LOCK(); 1622 | if (BufferIndex > 0u) { 1623 | _SEGGER_RTT.aUp[BufferIndex].sName = sName; 1624 | _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; 1625 | _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; 1626 | _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; 1627 | _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; 1628 | } 1629 | _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; 1630 | SEGGER_RTT_UNLOCK(); 1631 | r = 0; 1632 | } else { 1633 | r = -1; 1634 | } 1635 | return r; 1636 | } 1637 | 1638 | /********************************************************************* 1639 | * 1640 | * SEGGER_RTT_ConfigDownBuffer 1641 | * 1642 | * Function description 1643 | * Run-time configuration of a specific down-buffer (H->T). 1644 | * Buffer to be configured is specified by index. 1645 | * This includes: Buffer address, size, name, flags, ... 1646 | * 1647 | * Parameters 1648 | * BufferIndex Index of the buffer to configure. 1649 | * sName Pointer to a constant name string. 1650 | * pBuffer Pointer to a buffer to be used. 1651 | * BufferSize Size of the buffer. 1652 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1653 | * 1654 | * Return value 1655 | * >= 0 O.K. 1656 | * < 0 Error 1657 | * 1658 | * Additional information 1659 | * Buffer 0 is configured on compile-time. 1660 | * May only be called once per buffer. 1661 | * Buffer name and flags can be reconfigured using the appropriate functions. 1662 | */ 1663 | int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1664 | int r; 1665 | 1666 | INIT(); 1667 | if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { 1668 | SEGGER_RTT_LOCK(); 1669 | if (BufferIndex > 0u) { 1670 | _SEGGER_RTT.aDown[BufferIndex].sName = sName; 1671 | _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; 1672 | _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; 1673 | _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; 1674 | _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; 1675 | } 1676 | _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; 1677 | SEGGER_RTT_UNLOCK(); 1678 | r = 0; 1679 | } else { 1680 | r = -1; 1681 | } 1682 | return r; 1683 | } 1684 | 1685 | /********************************************************************* 1686 | * 1687 | * SEGGER_RTT_SetNameUpBuffer 1688 | * 1689 | * Function description 1690 | * Run-time configuration of a specific up-buffer name (T->H). 1691 | * Buffer to be configured is specified by index. 1692 | * 1693 | * Parameters 1694 | * BufferIndex Index of the buffer to renamed. 1695 | * sName Pointer to a constant name string. 1696 | * 1697 | * Return value 1698 | * >= 0 O.K. 1699 | * < 0 Error 1700 | */ 1701 | int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { 1702 | int r; 1703 | 1704 | INIT(); 1705 | if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { 1706 | SEGGER_RTT_LOCK(); 1707 | _SEGGER_RTT.aUp[BufferIndex].sName = sName; 1708 | SEGGER_RTT_UNLOCK(); 1709 | r = 0; 1710 | } else { 1711 | r = -1; 1712 | } 1713 | return r; 1714 | } 1715 | 1716 | /********************************************************************* 1717 | * 1718 | * SEGGER_RTT_SetNameDownBuffer 1719 | * 1720 | * Function description 1721 | * Run-time configuration of a specific Down-buffer name (T->H). 1722 | * Buffer to be configured is specified by index. 1723 | * 1724 | * Parameters 1725 | * BufferIndex Index of the buffer to renamed. 1726 | * sName Pointer to a constant name string. 1727 | * 1728 | * Return value 1729 | * >= 0 O.K. 1730 | * < 0 Error 1731 | */ 1732 | int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { 1733 | int r; 1734 | 1735 | INIT(); 1736 | if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { 1737 | SEGGER_RTT_LOCK(); 1738 | _SEGGER_RTT.aDown[BufferIndex].sName = sName; 1739 | SEGGER_RTT_UNLOCK(); 1740 | r = 0; 1741 | } else { 1742 | r = -1; 1743 | } 1744 | return r; 1745 | } 1746 | 1747 | /********************************************************************* 1748 | * 1749 | * SEGGER_RTT_SetFlagsUpBuffer 1750 | * 1751 | * Function description 1752 | * Run-time configuration of specific up-buffer flags (T->H). 1753 | * Buffer to be configured is specified by index. 1754 | * 1755 | * Parameters 1756 | * BufferIndex Index of the buffer. 1757 | * Flags Flags to set for the buffer. 1758 | * 1759 | * Return value 1760 | * >= 0 O.K. 1761 | * < 0 Error 1762 | */ 1763 | int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { 1764 | int r; 1765 | 1766 | INIT(); 1767 | if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { 1768 | SEGGER_RTT_LOCK(); 1769 | _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; 1770 | SEGGER_RTT_UNLOCK(); 1771 | r = 0; 1772 | } else { 1773 | r = -1; 1774 | } 1775 | return r; 1776 | } 1777 | 1778 | /********************************************************************* 1779 | * 1780 | * SEGGER_RTT_SetFlagsDownBuffer 1781 | * 1782 | * Function description 1783 | * Run-time configuration of specific Down-buffer flags (T->H). 1784 | * Buffer to be configured is specified by index. 1785 | * 1786 | * Parameters 1787 | * BufferIndex Index of the buffer to renamed. 1788 | * Flags Flags to set for the buffer. 1789 | * 1790 | * Return value 1791 | * >= 0 O.K. 1792 | * < 0 Error 1793 | */ 1794 | int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { 1795 | int r; 1796 | 1797 | INIT(); 1798 | if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { 1799 | SEGGER_RTT_LOCK(); 1800 | _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; 1801 | SEGGER_RTT_UNLOCK(); 1802 | r = 0; 1803 | } else { 1804 | r = -1; 1805 | } 1806 | return r; 1807 | } 1808 | 1809 | /********************************************************************* 1810 | * 1811 | * SEGGER_RTT_Init 1812 | * 1813 | * Function description 1814 | * Initializes the RTT Control Block. 1815 | * Should be used in RAM targets, at start of the application. 1816 | * 1817 | */ 1818 | void SEGGER_RTT_Init (void) { 1819 | _DoInit(); 1820 | } 1821 | 1822 | /********************************************************************* 1823 | * 1824 | * SEGGER_RTT_SetTerminal 1825 | * 1826 | * Function description 1827 | * Sets the terminal to be used for output on channel 0. 1828 | * 1829 | * Parameters 1830 | * TerminalId Index of the terminal. 1831 | * 1832 | * Return value 1833 | * >= 0 O.K. 1834 | * < 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) 1835 | */ 1836 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { 1837 | unsigned char ac[2]; 1838 | SEGGER_RTT_BUFFER_UP* pRing; 1839 | unsigned Avail; 1840 | int r; 1841 | // 1842 | INIT(); 1843 | // 1844 | r = 0; 1845 | ac[0] = 0xFFu; 1846 | if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels 1847 | ac[1] = _aTerminalId[TerminalId]; 1848 | pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed 1849 | 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 1850 | if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1851 | _ActiveTerminal = TerminalId; 1852 | _WriteBlocking(pRing, (const char*)ac, 2u); 1853 | } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes 1854 | Avail = _GetAvailWriteSpace(pRing); 1855 | if (Avail >= 2) { 1856 | _ActiveTerminal = TerminalId; // Only change active terminal in case of success 1857 | _WriteNoCheck(pRing, (const char*)ac, 2u); 1858 | } else { 1859 | r = -1; 1860 | } 1861 | } 1862 | SEGGER_RTT_UNLOCK(); 1863 | } else { 1864 | r = -1; 1865 | } 1866 | return r; 1867 | } 1868 | 1869 | /********************************************************************* 1870 | * 1871 | * SEGGER_RTT_TerminalOut 1872 | * 1873 | * Function description 1874 | * Writes a string to the given terminal 1875 | * without changing the terminal for channel 0. 1876 | * 1877 | * Parameters 1878 | * TerminalId Index of the terminal. 1879 | * s String to be printed on the terminal. 1880 | * 1881 | * Return value 1882 | * >= 0 - Number of bytes written. 1883 | * < 0 - Error. 1884 | * 1885 | */ 1886 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { 1887 | int Status; 1888 | unsigned FragLen; 1889 | unsigned Avail; 1890 | SEGGER_RTT_BUFFER_UP* pRing; 1891 | // 1892 | INIT(); 1893 | // 1894 | // Validate terminal ID. 1895 | // 1896 | if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels 1897 | // 1898 | // Get "to-host" ring buffer. 1899 | // 1900 | pRing = &_SEGGER_RTT.aUp[0]; 1901 | // 1902 | // Need to be able to change terminal, write data, change back. 1903 | // Compute the fixed and variable sizes. 1904 | // 1905 | FragLen = STRLEN(s); 1906 | // 1907 | // How we output depends upon the mode... 1908 | // 1909 | SEGGER_RTT_LOCK(); 1910 | Avail = _GetAvailWriteSpace(pRing); 1911 | switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { 1912 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1913 | // 1914 | // If we are in skip mode and there is no space for the whole 1915 | // of this output, don't bother switching terminals at all. 1916 | // 1917 | if (Avail < (FragLen + 4u)) { 1918 | Status = 0; 1919 | } else { 1920 | _PostTerminalSwitch(pRing, TerminalId); 1921 | Status = (int)_WriteBlocking(pRing, s, FragLen); 1922 | _PostTerminalSwitch(pRing, _ActiveTerminal); 1923 | } 1924 | break; 1925 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1926 | // 1927 | // If we are in trim mode and there is not enough space for everything, 1928 | // trim the output but always include the terminal switch. If no room 1929 | // for terminal switch, skip that totally. 1930 | // 1931 | if (Avail < 4u) { 1932 | Status = -1; 1933 | } else { 1934 | _PostTerminalSwitch(pRing, TerminalId); 1935 | Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); 1936 | _PostTerminalSwitch(pRing, _ActiveTerminal); 1937 | } 1938 | break; 1939 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1940 | // 1941 | // If we are in blocking mode, output everything. 1942 | // 1943 | _PostTerminalSwitch(pRing, TerminalId); 1944 | Status = (int)_WriteBlocking(pRing, s, FragLen); 1945 | _PostTerminalSwitch(pRing, _ActiveTerminal); 1946 | break; 1947 | default: 1948 | Status = -1; 1949 | break; 1950 | } 1951 | // 1952 | // Finish up. 1953 | // 1954 | SEGGER_RTT_UNLOCK(); 1955 | } else { 1956 | Status = -1; 1957 | } 1958 | return Status; 1959 | } 1960 | 1961 | /********************************************************************* 1962 | * 1963 | * SEGGER_RTT_GetAvailWriteSpace 1964 | * 1965 | * Function description 1966 | * Returns the number of bytes available in the ring buffer. 1967 | * 1968 | * Parameters 1969 | * BufferIndex Index of the up buffer. 1970 | * 1971 | * Return value 1972 | * Number of bytes that are free in the selected up buffer. 1973 | */ 1974 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex){ 1975 | return _GetAvailWriteSpace(&_SEGGER_RTT.aUp[BufferIndex]); 1976 | } 1977 | 1978 | 1979 | /********************************************************************* 1980 | * 1981 | * SEGGER_RTT_GetBytesInBuffer() 1982 | * 1983 | * Function description 1984 | * Returns the number of bytes currently used in the up buffer. 1985 | * 1986 | * Parameters 1987 | * BufferIndex Index of the up buffer. 1988 | * 1989 | * Return value 1990 | * Number of bytes that are used in the buffer. 1991 | */ 1992 | unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { 1993 | unsigned RdOff; 1994 | unsigned WrOff; 1995 | unsigned r; 1996 | // 1997 | // Avoid warnings regarding volatile access order. It's not a problem 1998 | // in this case, but dampen compiler enthusiasm. 1999 | // 2000 | RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff; 2001 | WrOff = _SEGGER_RTT.aUp[BufferIndex].WrOff; 2002 | if (RdOff <= WrOff) { 2003 | r = WrOff - RdOff; 2004 | } else { 2005 | r = _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); 2006 | } 2007 | return r; 2008 | } 2009 | 2010 | /*************************** End of file ****************************/ 2011 | -------------------------------------------------------------------------------- /seggerRtt代码包/SEGGER_RTT.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2019 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: 6.70a * 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: 17697 $ 55 | ---------------------------------------------------------------------- 56 | */ 57 | 58 | #ifndef SEGGER_RTT_H 59 | #define SEGGER_RTT_H 60 | 61 | #include "SEGGER_RTT_Conf.h" 62 | 63 | 64 | 65 | /********************************************************************* 66 | * 67 | * Defines, defaults 68 | * 69 | ********************************************************************** 70 | */ 71 | #ifndef RTT_USE_ASM 72 | #if (defined __SES_ARM) // SEGGER Embedded Studio 73 | #define _CC_HAS_RTT_ASM_SUPPORT 1 74 | #elif (defined __CROSSWORKS_ARM) // Rowley Crossworks 75 | #define _CC_HAS_RTT_ASM_SUPPORT 1 76 | #elif (defined __GNUC__) // GCC 77 | #define _CC_HAS_RTT_ASM_SUPPORT 1 78 | #elif (defined __clang__) // Clang compiler 79 | #define _CC_HAS_RTT_ASM_SUPPORT 1 80 | #elif (defined __IASMARM__) // IAR assembler 81 | #define _CC_HAS_RTT_ASM_SUPPORT 1 82 | #elif (defined __ICCARM__) // IAR compiler 83 | #define _CC_HAS_RTT_ASM_SUPPORT 1 84 | #else 85 | #define _CC_HAS_RTT_ASM_SUPPORT 0 86 | #endif 87 | #if (defined __ARM_ARCH_7M__) // Cortex-M3/4 88 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 89 | #elif (defined __ARM_ARCH_7EM__) // Cortex-M7 90 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 91 | #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 92 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 93 | #elif (defined __ARM7M__) // IAR Cortex-M3/4 94 | #if (__CORE__ == __ARM7M__) 95 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 96 | #else 97 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 98 | #endif 99 | #elif (defined __ARM7EM__) // IAR Cortex-M7 100 | #if (__CORE__ == __ARM7EM__) 101 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 102 | #else 103 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 104 | #endif 105 | #else 106 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 107 | #endif 108 | // 109 | // If IDE and core support the ASM version, enable ASM version by default 110 | // 111 | #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) 112 | #define RTT_USE_ASM (1) 113 | #else 114 | #define RTT_USE_ASM (0) 115 | #endif 116 | #endif 117 | 118 | #ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file 119 | #include 120 | #include 121 | 122 | /********************************************************************* 123 | * 124 | * Defines, fixed 125 | * 126 | ********************************************************************** 127 | */ 128 | 129 | /********************************************************************* 130 | * 131 | * Types 132 | * 133 | ********************************************************************** 134 | */ 135 | 136 | // 137 | // Description for a circular buffer (also called "ring buffer") 138 | // which is used as up-buffer (T->H) 139 | // 140 | typedef struct { 141 | const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" 142 | char* pBuffer; // Pointer to start of buffer 143 | 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. 144 | unsigned WrOff; // Position of next item to be written by either target. 145 | volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. 146 | unsigned Flags; // Contains configuration flags 147 | } SEGGER_RTT_BUFFER_UP; 148 | 149 | // 150 | // Description for a circular buffer (also called "ring buffer") 151 | // which is used as down-buffer (H->T) 152 | // 153 | typedef struct { 154 | const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" 155 | char* pBuffer; // Pointer to start of buffer 156 | 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. 157 | volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. 158 | unsigned RdOff; // Position of next item to be read by target (down-buffer). 159 | unsigned Flags; // Contains configuration flags 160 | } SEGGER_RTT_BUFFER_DOWN; 161 | 162 | // 163 | // RTT control block which describes the number of buffers available 164 | // as well as the configuration for each buffer 165 | // 166 | // 167 | typedef struct { 168 | char acID[16]; // Initialized to "SEGGER RTT" 169 | int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) 170 | int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) 171 | SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host 172 | SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target 173 | } SEGGER_RTT_CB; 174 | 175 | /********************************************************************* 176 | * 177 | * Global data 178 | * 179 | ********************************************************************** 180 | */ 181 | extern SEGGER_RTT_CB _SEGGER_RTT; 182 | 183 | /********************************************************************* 184 | * 185 | * RTT API functions 186 | * 187 | ********************************************************************** 188 | */ 189 | #ifdef __cplusplus 190 | extern "C" { 191 | #endif 192 | int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 193 | int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 194 | int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 195 | int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 196 | int SEGGER_RTT_GetKey (void); 197 | unsigned SEGGER_RTT_HasData (unsigned BufferIndex); 198 | int SEGGER_RTT_HasKey (void); 199 | unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); 200 | void SEGGER_RTT_Init (void); 201 | unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 202 | unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 203 | int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); 204 | int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); 205 | int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); 206 | int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); 207 | int SEGGER_RTT_WaitKey (void); 208 | unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 209 | unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 210 | unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 211 | unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 212 | unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); 213 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 214 | unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); 215 | unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); 216 | unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); 217 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); 218 | unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); 219 | // 220 | // Function macro for performance optimization 221 | // 222 | #define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) 223 | 224 | #if RTT_USE_ASM 225 | #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock 226 | #endif 227 | 228 | /********************************************************************* 229 | * 230 | * RTT transfer functions to send RTT data via other channels. 231 | * 232 | ********************************************************************** 233 | */ 234 | unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 235 | unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 236 | unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 237 | unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 238 | 239 | #define SEGGER_RTT_HASDATA_UP(n) (_SEGGER_RTT.aUp[n].WrOff - _SEGGER_RTT.aUp[n].RdOff) 240 | 241 | /********************************************************************* 242 | * 243 | * RTT "Terminal" API functions 244 | * 245 | ********************************************************************** 246 | */ 247 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId); 248 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); 249 | 250 | /********************************************************************* 251 | * 252 | * RTT printf functions (require SEGGER_RTT_printf.c) 253 | * 254 | ********************************************************************** 255 | */ 256 | int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); 257 | int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); 258 | 259 | #ifdef __cplusplus 260 | } 261 | #endif 262 | 263 | #endif // ifndef(SEGGER_RTT_ASM) 264 | 265 | /********************************************************************* 266 | * 267 | * Defines 268 | * 269 | ********************************************************************** 270 | */ 271 | 272 | // 273 | // Operating modes. Define behavior if buffer is full (not enough space for entire message) 274 | // 275 | #define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) 276 | #define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. 277 | #define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. 278 | #define SEGGER_RTT_MODE_MASK (3) 279 | 280 | // 281 | // Control sequences, based on ANSI. 282 | // Can be used to control color, and clear the screen 283 | // 284 | #define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors 285 | #define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left 286 | 287 | #define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" 288 | #define RTT_CTRL_TEXT_RED "\x1B[2;31m" 289 | #define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" 290 | #define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" 291 | #define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" 292 | #define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" 293 | #define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" 294 | #define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" 295 | 296 | #define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" 297 | #define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" 298 | #define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" 299 | #define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" 300 | #define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" 301 | #define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" 302 | #define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" 303 | #define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" 304 | 305 | #define RTT_CTRL_BG_BLACK "\x1B[24;40m" 306 | #define RTT_CTRL_BG_RED "\x1B[24;41m" 307 | #define RTT_CTRL_BG_GREEN "\x1B[24;42m" 308 | #define RTT_CTRL_BG_YELLOW "\x1B[24;43m" 309 | #define RTT_CTRL_BG_BLUE "\x1B[24;44m" 310 | #define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" 311 | #define RTT_CTRL_BG_CYAN "\x1B[24;46m" 312 | #define RTT_CTRL_BG_WHITE "\x1B[24;47m" 313 | 314 | #define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" 315 | #define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" 316 | #define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" 317 | #define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" 318 | #define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" 319 | #define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" 320 | #define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" 321 | #define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" 322 | 323 | 324 | #endif 325 | 326 | /*************************** End of file ****************************/ 327 | -------------------------------------------------------------------------------- /seggerRtt代码包/SEGGER_RTT_Conf.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2019 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: 6.70a * 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: 18601 $ 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 | /********************************************************************* 66 | * 67 | * Defines, configurable 68 | * 69 | ********************************************************************** 70 | */ 71 | #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 72 | #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) 73 | #endif 74 | 75 | #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 76 | #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) 77 | #endif 78 | 79 | #ifndef BUFFER_SIZE_UP 80 | #define BUFFER_SIZE_UP (512) // Size of the buffer for terminal output of target, up to host (Default: 1k) 81 | #endif 82 | 83 | #ifndef BUFFER_SIZE_DOWN 84 | #define BUFFER_SIZE_DOWN (64) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) 85 | #endif 86 | 87 | #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE 88 | #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) 89 | #endif 90 | 91 | #ifndef SEGGER_RTT_MODE_DEFAULT 92 | #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) 93 | #endif 94 | 95 | /********************************************************************* 96 | * 97 | * RTT memcpy configuration 98 | * 99 | * memcpy() is good for large amounts of data, 100 | * but the overhead is big for small amounts, which are usually stored via RTT. 101 | * With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. 102 | * 103 | * SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. 104 | * This is may be required with memory access restrictions, 105 | * such as on Cortex-A devices with MMU. 106 | */ 107 | #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP 108 | #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop 109 | #endif 110 | // 111 | // Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets 112 | // 113 | //#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) 114 | // #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) 115 | //#endif 116 | 117 | // 118 | // Target is not allowed to perform other RTT operations while string still has not been stored completely. 119 | // Otherwise we would probably end up with a mixed string in the buffer. 120 | // If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. 121 | // 122 | // SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. 123 | // Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. 124 | // When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. 125 | // (Higher priority = lower priority number) 126 | // Default value for embOS: 128u 127 | // Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) 128 | // In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC 129 | // or define SEGGER_RTT_LOCK() to completely disable interrupts. 130 | // 131 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 132 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) 133 | #endif 134 | 135 | /********************************************************************* 136 | * 137 | * RTT lock configuration for SEGGER Embedded Studio, 138 | * Rowley CrossStudio and GCC 139 | */ 140 | #if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32)) 141 | #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) 142 | #define SEGGER_RTT_LOCK() { \ 143 | unsigned int LockState; \ 144 | __asm volatile ("mrs %0, primask \n\t" \ 145 | "movs r1, $1 \n\t" \ 146 | "msr primask, r1 \n\t" \ 147 | : "=r" (LockState) \ 148 | : \ 149 | : "r1" \ 150 | ); 151 | 152 | #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ 153 | : \ 154 | : "r" (LockState) \ 155 | : \ 156 | ); \ 157 | } 158 | #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) 159 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 160 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 161 | #endif 162 | #define SEGGER_RTT_LOCK() { \ 163 | unsigned int LockState; \ 164 | __asm volatile ("mrs %0, basepri \n\t" \ 165 | "mov r1, %1 \n\t" \ 166 | "msr basepri, r1 \n\t" \ 167 | : "=r" (LockState) \ 168 | : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ 169 | : "r1" \ 170 | ); 171 | 172 | #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ 173 | : \ 174 | : "r" (LockState) \ 175 | : \ 176 | ); \ 177 | } 178 | 179 | #elif defined(__ARM_ARCH_7A__) 180 | #define SEGGER_RTT_LOCK() { \ 181 | unsigned int LockState; \ 182 | __asm volatile ("mrs r1, CPSR \n\t" \ 183 | "mov %0, r1 \n\t" \ 184 | "orr r1, r1, #0xC0 \n\t" \ 185 | "msr CPSR_c, r1 \n\t" \ 186 | : "=r" (LockState) \ 187 | : \ 188 | : "r1" \ 189 | ); 190 | 191 | #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ 192 | "mrs r1, CPSR \n\t" \ 193 | "bic r1, r1, #0xC0 \n\t" \ 194 | "and r0, r0, #0xC0 \n\t" \ 195 | "orr r1, r1, r0 \n\t" \ 196 | "msr CPSR_c, r1 \n\t" \ 197 | : \ 198 | : "r" (LockState) \ 199 | : "r0", "r1" \ 200 | ); \ 201 | } 202 | #elif defined(__riscv) || defined(__riscv_xlen) 203 | #define SEGGER_RTT_LOCK() { \ 204 | unsigned int LockState; \ 205 | __asm volatile ("csrr %0, mstatus \n\t" \ 206 | "csrci mstatus, 8 \n\t" \ 207 | "andi %0, %0, 8 \n\t" \ 208 | : "=r" (LockState) \ 209 | : \ 210 | : \ 211 | ); 212 | 213 | #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \ 214 | "or %0, %0, a1 \n\t" \ 215 | "csrs mstatus, %0 \n\t" \ 216 | : \ 217 | : "r" (LockState) \ 218 | : "a1" \ 219 | ); \ 220 | } 221 | #else 222 | #define SEGGER_RTT_LOCK() 223 | #define SEGGER_RTT_UNLOCK() 224 | #endif 225 | #endif 226 | 227 | /********************************************************************* 228 | * 229 | * RTT lock configuration for IAR EWARM 230 | */ 231 | #ifdef __ICCARM__ 232 | #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \ 233 | (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) 234 | #define SEGGER_RTT_LOCK() { \ 235 | unsigned int LockState; \ 236 | LockState = __get_PRIMASK(); \ 237 | __set_PRIMASK(1); 238 | 239 | #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ 240 | } 241 | #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \ 242 | (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \ 243 | (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \ 244 | (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) 245 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 246 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 247 | #endif 248 | #define SEGGER_RTT_LOCK() { \ 249 | unsigned int LockState; \ 250 | LockState = __get_BASEPRI(); \ 251 | __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); 252 | 253 | #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ 254 | } 255 | #endif 256 | #endif 257 | 258 | /********************************************************************* 259 | * 260 | * RTT lock configuration for IAR RX 261 | */ 262 | #ifdef __ICCRX__ 263 | #define SEGGER_RTT_LOCK() { \ 264 | unsigned long LockState; \ 265 | LockState = __get_interrupt_state(); \ 266 | __disable_interrupt(); 267 | 268 | #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ 269 | } 270 | #endif 271 | 272 | /********************************************************************* 273 | * 274 | * RTT lock configuration for IAR RL78 275 | */ 276 | #ifdef __ICCRL78__ 277 | #define SEGGER_RTT_LOCK() { \ 278 | __istate_t LockState; \ 279 | LockState = __get_interrupt_state(); \ 280 | __disable_interrupt(); 281 | 282 | #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ 283 | } 284 | #endif 285 | 286 | /********************************************************************* 287 | * 288 | * RTT lock configuration for KEIL ARM 289 | */ 290 | #ifdef __CC_ARM 291 | #if (defined __TARGET_ARCH_6S_M) 292 | #define SEGGER_RTT_LOCK() { \ 293 | unsigned int LockState; \ 294 | register unsigned char PRIMASK __asm( "primask"); \ 295 | LockState = PRIMASK; \ 296 | PRIMASK = 1u; \ 297 | __schedule_barrier(); 298 | 299 | #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ 300 | __schedule_barrier(); \ 301 | } 302 | #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) 303 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 304 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 305 | #endif 306 | #define SEGGER_RTT_LOCK() { \ 307 | unsigned int LockState; \ 308 | register unsigned char BASEPRI __asm( "basepri"); \ 309 | LockState = BASEPRI; \ 310 | BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ 311 | __schedule_barrier(); 312 | 313 | #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ 314 | __schedule_barrier(); \ 315 | } 316 | #endif 317 | #endif 318 | 319 | /********************************************************************* 320 | * 321 | * RTT lock configuration for TI ARM 322 | */ 323 | #ifdef __TI_ARM__ 324 | #if defined (__TI_ARM_V6M0__) 325 | #define SEGGER_RTT_LOCK() { \ 326 | unsigned int LockState; \ 327 | LockState = __get_PRIMASK(); \ 328 | __set_PRIMASK(1); 329 | 330 | #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ 331 | } 332 | #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) 333 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 334 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 335 | #endif 336 | #define SEGGER_RTT_LOCK() { \ 337 | unsigned int LockState; \ 338 | LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); 339 | 340 | #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \ 341 | } 342 | #endif 343 | #endif 344 | 345 | /********************************************************************* 346 | * 347 | * RTT lock configuration for CCRX 348 | */ 349 | #ifdef __RX 350 | #define SEGGER_RTT_LOCK() { \ 351 | unsigned long LockState; \ 352 | LockState = get_psw() & 0x010000; \ 353 | clrpsw_i(); 354 | 355 | #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \ 356 | } 357 | #endif 358 | 359 | /********************************************************************* 360 | * 361 | * RTT lock configuration for embOS Simulation on Windows 362 | * (Can also be used for generic RTT locking with embOS) 363 | */ 364 | #if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS) 365 | 366 | void OS_SIM_EnterCriticalSection(void); 367 | void OS_SIM_LeaveCriticalSection(void); 368 | 369 | #define SEGGER_RTT_LOCK() { \ 370 | OS_SIM_EnterCriticalSection(); 371 | 372 | #define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \ 373 | } 374 | #endif 375 | 376 | /********************************************************************* 377 | * 378 | * RTT lock configuration fallback 379 | */ 380 | #ifndef SEGGER_RTT_LOCK 381 | #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) 382 | #endif 383 | 384 | #ifndef SEGGER_RTT_UNLOCK 385 | #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) 386 | #endif 387 | 388 | #endif 389 | /*************************** End of file ****************************/ 390 | -------------------------------------------------------------------------------- /seggerRtt代码包/SEGGER_RTT_printf.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2019 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: 6.70a * 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 | -------------------------------------------------------------------------------- /打包完成的exe程序/chipList.json: -------------------------------------------------------------------------------- 1 | { 2 | "chipList": 3 | [ 4 | "STM32L031G6", 5 | "STM32F407IG", 6 | "STM32F407VE", 7 | "STM32F407ZG", 8 | "STM32F427ZI" 9 | ], 10 | 11 | "default":"STM32L031G6" 12 | } 13 | -------------------------------------------------------------------------------- /打包完成的exe程序/resizeApi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/打包完成的exe程序/resizeApi.png -------------------------------------------------------------------------------- /打包完成的exe程序/rtt2telnet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcujackson/Rtt2Telnet/136176b6d1e74824d7dedf49847784692bcf6e1a/打包完成的exe程序/rtt2telnet.exe --------------------------------------------------------------------------------