├── .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 | 
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 | 
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 | 
89 |
90 | + 1.首先打开工程目录下的chipList.json
91 | 这是一个json格式的文件,可以将自己常用的芯片型号添加进列表中,记得加上逗号哦,不然程序解析错误可能会出现奔溃的情况,还可以将 "default":"STM32L031G6" 修改为自己最常用的芯片型号,这样在程序打开的时候就会直接选择该型号的芯片
92 |
93 | 
94 |
95 | 
96 |
97 | 若无需修改端口,直接点击开启按钮即可
98 |
99 | ### 2.3 使用SecureCRT登录Telnet服务器
100 |
101 | 1.如果在本机开启该软件,可以用直接用127.0.0.1的地址即可登录到telnet服务器,如下图
102 | 
103 |
104 | 
105 |
106 | ## 3 结合Shell使用
107 |
108 | 暂无,后续会进行补充
109 | 有兴趣的同学可以使用letter大神写的嵌入式shell
110 |
111 | https://github.com/NevermindZZT/letter-shell
112 |
113 | 结合本软件可以实现比较实用的调试功能,下面先放一张效果图
114 |
115 | 
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 |
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
--------------------------------------------------------------------------------