├── .gitignore ├── .idea ├── .gitignore ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── rtt-py.iml └── vcs.xml ├── JLinkARM.dll ├── LICENSE ├── README.md ├── __pycache__ ├── main.cpython-38.pyc ├── main.cpython-39.pyc └── qpt.cpython-39.pyc ├── apple.ico ├── apple.png ├── config.json ├── image ├── 1.gif ├── 2.gif └── 3.png ├── main.py ├── main.spec ├── rtt-t.log └── windows icon update.bat /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | build 3 | rtt-t.log -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/rtt-py.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /JLinkARM.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/JLinkARM.dll -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 bds123 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 | # RTT(Real Time Transfer) Tool(RTT-T) 2 | --- 3 | 4 | [RTT-T下载地址(windows平台)](https://github.com/liuhao1946/RTT-T-Project/releases) 5 | 6 | ### 描述 7 | 这是一个**J-Llink RTT**软件,用来接收由MCU通过SEGGER RTT发送的数据。相比官方J-Llink RTT Viewer软件,该软件有以下特点: 8 | * 使用python基于**PySampleGUI**编写 9 | 10 | * 接收RTT信息后能附带时间戳 11 | * 不会自动清除数据框中的数据,是否清除以及什么时候清除将由自己决定 12 | * 支持一键保存数据框中的所有数据 13 | * 支持实时记录数据到文件 14 | * 向上滚动鼠标滚动轮就能停止在当前界面。向下将滚动条滚到最低端就能实时看到当前接收到的数据 15 | * 每次连接J-Link都会复位MCU 16 | * 同步电脑时间到MCU 17 | * 通过RTT-T发送自定义数据到MCU 18 | 19 | --- 20 | ### 软件更新说明 21 | 当前最新版本为v1.5,相比v1.3版本,有以下不同 22 | * 修补了v1.3版本的bug 23 | 24 | * 当软件内部出现异常时,能够将详细的异常信息输出到rtt-t.log中 25 | 26 | ![](https://github.com/liuhao1946/RTT-T-Project/blob/master/image/3.png) 27 | 28 | --- 29 | ### RTT-T功能演示 30 | 31 | ![](https://github.com/liuhao1946/RTT-T-Project/blob/master/image/1.gif) 32 | 33 | --- 34 | ### RTT-T的使用说明 35 | * RTT-T自身打印出来的信息是开头带有LOG:xxx的字符串 36 | 37 | * RTT-T使用的是**0数据通道**,这意味着MCU也必须使用SEGGER RTT的**0数据通道** 38 | 39 | ```c 40 | SEGGER_RTT_printf(0,"test\n"); 41 | ``` 42 | 43 | * 如果MCU端要获得到RTT-T的数据,有两个地方需要留意 44 | 1. 将MCU中RTT模块的接收缓存设置到合适的长度 45 | 46 | 2. MCU在程序中做如下轮训调用,以查询RTT发送过来的数据: 47 | ```c 48 | #include "string.h" 49 | 50 | uint8_t rtt_rx_data[33]; 51 | 52 | void str_to_int(char *p, int32_t *pv) 53 | { 54 | uint8_t sign; 55 | char c; 56 | 57 | sign = *p; 58 | if (p[0] == '-' || p[0] == '+') 59 | { 60 | p++; 61 | } 62 | *pv = 0; 63 | while (*p >= '0' && *p <= '9') 64 | { 65 | c = *p++; 66 | *pv = *pv * 10 + (c-'0'); 67 | } 68 | 69 | *pv = (sign != '-') ? *pv: -(*pv); 70 | } 71 | 72 | void timer_10ms(void ) 73 | { 74 | uint8_t len; 75 | 76 | len = SEGGER_RTT_Read(0, rtt_rx_data, 32); 77 | rtt_rx_data[len] = 0; 78 | 79 | if(len > 0) 80 | { 81 | char *p; 82 | char temp[6]; 83 | uint8_t time[6]; 84 | int32_t temp_dt; 85 | 86 | p = strstr(rtt_rx_data, "time syn:"); 87 | //time syn:2022-01-16-16-27-30 88 | if(p != 0) 89 | { 90 | uint8_t i; 91 | 92 | p = p + 11; 93 | memset(temp,0,6); 94 | //字符串时间转换为整形,结果保存在time中 95 | for(i = 0; i < 6; i++) 96 | { 97 | memcpy(temp,p,2); 98 | str_to_int(temp, &temp_dt); 99 | time[i] = temp_dt; 100 | p += 3; 101 | } 102 | 103 | } 104 | 105 | } 106 | } 107 | ``` 108 | 109 | * 如果需要同步电脑时间到MCU 110 | 1. 连接J-Llink 111 | 112 | 2. 在Text Data输入框中输入字符串指令"cmd:time syn"(软件默认) 113 | 114 | 3. 点击Send按钮,RTT-T会将如下字符串格式的电脑时间发送到MCU 115 | 116 | "time syn:2022-01-16-15-08-05" 117 | 118 | * 打开**实时数据保存**或者**保存数据框中的全部数据**时,RTT-T会自动在应用程序所在目录创建文件 119 | 120 | 实时数据保存的文件名称:real_time_log_xxx(xxx为年月日时分秒) 121 | 122 | 保存数据框中的全部数据文件名称:log_xxx(xxx为年月日时分秒) 123 | 124 | * Rx Timeout参数的说明 125 | 这个参数的含义是在RTT-T每次接收到一笔数据(≥1)后,RTT-T都会等待Rx Timeout(ms)。在Rx Timeout内接收到的数据RTT-T认为是一包数据。当超过Rx Timeout后,RTT-T就会为这包数据打上一个时间戳(如果时间戳打开的话)。这可以更好的辅助RTT-T在合适的数据位置打上时间戳。 126 | 127 | 如果Rx Timeout = 0,表示RTT-T不使用超时机制,这可能造成的一个问题是时间戳的位置打的不准。 128 | 129 | **注:** 130 | **如果设置Rx Timeout,该值应该至少≥2(ms),推荐≥10(ms)** 131 | 132 | * 如果需要源码,这里需要提醒一下 133 | 134 | 1. 软件依赖的主要的第三方库为: 135 | 136 | [PySimpleGUI](https://github.com/PySimpleGUI/PySimpleGUI) 137 | 138 | [pylink-square](https://github.com/square/pylink) 139 | 140 | 2. 源码中使用的PySimpleGUI版本为4.51.1。我在该版本中增加了获得数据框滚动条相对位置的函数(官方没有提供这个接口),因此你在安装了PySimpleGUI后,还需要在PySimpleGUI.py中增加下面代码(就放在set_vscroll_position()函数后面,这个函数是PySimpleGUI中存在的) 141 | ```python 142 | def get_vscroll_position(self): 143 | """ 144 | Get the relative position of the scrollbar 145 | 146 | :return: (y1,y2) 147 | :rtype: tuple 148 | """ 149 | try: 150 | return self.Widget.yview() 151 | except Exception as e: 152 | print('Warning get the vertical scroll (yview failed)') 153 | print(e) 154 | return None 155 | ``` 156 | --- 157 | 158 | ### RTT-T的配置 159 | 160 | 由于配置选项一般不会变动,所以软件相关的可配置选项全部放在了**应用程序所在目录**下的**config.json**中。如需要修改配置,通过修改这个文件中相应的参数即可。具体如下: 161 | 162 | **增加芯片型号** 163 | * 打开官方J-Link RTT Viewer软件,找到你需要的芯片型号(比如,需要增加**nRF52840_xxAA**) 164 | 165 | * 打开config.json文件,将芯片型号添加到"chip model"中 166 | 167 | ![](https://github.com/liuhao1946/RTT-T-Project/blob/master/image/2.gif) 168 | 169 | **更换数据框中的字体** 170 | 171 | 打开config.json文件,将需要的字体放在"font"列表的第一项(类似添加nRF52840_xxAA) 172 | 173 | **更换数据框中的字体大小** 174 | 175 | 打开config.json文件,修改"font size"中的数字,数字越大,字体越大 176 | 177 | **修改软件启动时数据框的宽度,以兼容不同电脑屏幕尺寸** 178 | 179 | 打开config.json文件,修改"data window width",默认是83,可以在此基础上增大或者减少 180 | 181 | **注:修改config.json文件后保存,然后重启软件,新修改的参数才会生效** 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /__pycache__/main.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/__pycache__/main.cpython-38.pyc -------------------------------------------------------------------------------- /__pycache__/main.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/__pycache__/main.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/qpt.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/__pycache__/qpt.cpython-39.pyc -------------------------------------------------------------------------------- /apple.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/apple.ico -------------------------------------------------------------------------------- /apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/apple.png -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "chip model" : [ 3 | "nRF52840_xxAA", 4 | "nRF52832_xxAA", 5 | "nRF52832_xxAB", 6 | "STM32F1034C8" 7 | ], 8 | "jlink interface" : ["SWD"], 9 | "Rx Timeout": "0", 10 | "Speed" : "4000", 11 | "SN" : "", 12 | "font" : [ 13 | "Consolas", 14 | "Calibri" 15 | ], 16 | "font size" :"13", 17 | "data window width" : "83" 18 | } -------------------------------------------------------------------------------- /image/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/image/1.gif -------------------------------------------------------------------------------- /image/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/image/2.gif -------------------------------------------------------------------------------- /image/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhao1946/RTT-T-Project/08b1b2f055ce7fc9f203bd6ea5917707e494e71e/image/3.png -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # This is a sample Python script. 2 | 3 | # Press Shift+F10 to execute it or replace it with your code. 4 | # Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. 5 | 6 | 7 | import PySimpleGUI as sg 8 | import time 9 | from datetime import datetime 10 | import threading 11 | import pylink 12 | import re 13 | import json 14 | import logging 15 | #import traceback 16 | 17 | 18 | base64_main_icon = b'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' 19 | 20 | THREAD_RUN_INTERVAL_S = 0.002 21 | 22 | RTT_DATA_WIN = '-DB_OUT-'+sg.WRITE_ONLY_KEY 23 | 24 | class JlinkThread(threading.Thread): 25 | 26 | gui_wakeup_tick_th = 0 27 | 28 | def __init__(self, window,jlink,timestamp = False,thread_start=False): 29 | super().__init__(daemon=True) 30 | self._thread_start = thread_start 31 | self.jlink = jlink 32 | self.window = window 33 | self.timestamp = timestamp 34 | self.event = threading.Event() 35 | self.event.clear() 36 | 37 | def run(self): 38 | rtt_data_list = [] 39 | rtt_data_list_temp = [] 40 | gui_wake_tick = 0 41 | rtt_data_none_cnt = 0 42 | time_to = False 43 | 44 | while True: 45 | if self._thread_start: 46 | try: 47 | rtt_data_list_temp = self.jlink.rtt_read(0,2048) #1ms = 1k 48 | if len(rtt_data_list_temp): 49 | rtt_data_list = rtt_data_list + rtt_data_list_temp 50 | rtt_data_none_cnt = 0 51 | else: 52 | rtt_data_none_cnt = rtt_data_none_cnt + 1 53 | 54 | #Turn on the timeout function,self.gui_wakeup_tick_th != 0 55 | if self.gui_wakeup_tick_th != 0: 56 | if rtt_data_none_cnt >= self.gui_wakeup_tick_th: 57 | rtt_data_none_cnt = 0 58 | time_to = True 59 | else: 60 | #Turn off the timeout function, 10ms automatically submit data once to the GUI 61 | gui_wake_tick = gui_wake_tick + 1 62 | if gui_wake_tick >= 5: 63 | gui_wake_tick = 0 64 | time_to = True 65 | 66 | if time_to: 67 | time_to = False 68 | if len(rtt_data_list): 69 | str_data = ''.join([chr(i) for i in rtt_data_list]) 70 | if self.timestamp == True: 71 | str_data = '[' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[0:-3] + '] ' + str_data 72 | self.window.write_event_value('-JLINK_READ_DATA_THREAD-', str_data) 73 | rtt_data_list = [] 74 | 75 | time.sleep(THREAD_RUN_INTERVAL_S) 76 | except Exception as e: 77 | logging.debug('Thread:rtt error [' + str(e) + ']\n') 78 | print(str(e)) 79 | self.window.write_event_value('-JLINK_READ_DATA_THREAD-', 'J-Link connect lost') 80 | self._thread_start = False 81 | except : 82 | logging.debug('Thread:rtt error\n') 83 | self.window.write_event_value('-JLINK_READ_DATA_THREAD-', 'J-Link connect lost') 84 | self._thread_start = False 85 | else: 86 | print(rtt_data_list) 87 | logging.debug('Thread:rtt data length [' + str(len(rtt_data_list)) + ']') 88 | logging.debug('Thread:rtt data [' + ''.join([chr(i) for i in rtt_data_list]) +']') 89 | logging.debug('Thread:GUI wakeup tick threshold {}'.format(self.gui_wakeup_tick_th)) 90 | logging.debug('Thread:J-Link thread wait......') 91 | self.event.wait() 92 | self.event.clear() 93 | 94 | def jlink_thread_ctr(self, state): 95 | self._thread_start = state 96 | if state: 97 | self.event.set() 98 | logging.debug('Thread:J-Link thread enable') 99 | else: 100 | self.event.clear() 101 | logging.debug('Thread:J-Link thread disble') 102 | 103 | def jlink_timestamp_set(self, state): 104 | self.timestamp = state 105 | 106 | def jlink_reset(jlink): 107 | try: 108 | jlink.rtt_stop() 109 | except: 110 | print("rtt stop error\n") 111 | pass 112 | if jlink.opened(): 113 | jlink.close() 114 | 115 | def main(): 116 | logging.basicConfig(filename='rtt-t.log',filemode='w',encoding='utf-8', level=logging.DEBUG,\ 117 | format='%(asctime)s %(message)s',datefmt='%Y/%m/%d %I:%M:%S') 118 | logging.debug('----------------------------------------------------------------') 119 | logging.debug('----------------------------------------------------------------') 120 | logging.debug('---------------RTT-T Debug Log---------------') 121 | logging.debug('----------------------------------------------------------------') 122 | logging.debug('----------------------------------------------------------------') 123 | 124 | with open('config.json', 'r') as f: 125 | json_data = json.load(f) 126 | 127 | chip_list = json_data['chip model'] 128 | jk_interface_list = json_data['jlink interface'] 129 | jk_speed = json_data['Speed'] 130 | rx_timeout = json_data['Rx Timeout'] 131 | sn = json_data['SN'] 132 | font_type = json_data['font'][0] 133 | font_size = json_data['font size'] 134 | try: 135 | data_window_w = int(json_data['data window width']) 136 | except: 137 | data_window_w = 83 138 | 139 | font = font_type + ' ' 140 | 141 | jlink = pylink.JLink() 142 | right_click_menu = ['',['Clear','Scroll to the end']] 143 | 144 | cfg_frame_layout = [[sg.Button('Connect J-Link',pad=((45,3),(16,16)),key='-JK_CONNECT-',size=(18,2),button_color=('grey0','grey100'),font=(font+str(12)))],\ 145 | [sg.Button('Open Timestamp',key='-TIMESTAMP_CTR-',pad=((45,3),(16,16)),button_color=('grey0','grey100'),size=(18,2),font=(font+str(12)))],\ 146 | [sg.Button('Open Real-time saving data',key='-RT_DATA_SAVE-',pad=((45,3),(16,16)),size=(18,2),button_color=('grey0','grey100'),font=(font+str(12)))],\ 147 | [sg.Button('Save all data',key='-DATA_SAVE-',pad=((45,3),(16,16)),size=(18,2),button_color=('grey0','grey100'),font=(font+str(12)))],\ 148 | [sg.Text('Chip Model'),sg.Combo(chip_list,chip_list[0],size=(16,1),pad=((23,3),(20,16)),key='-CHIP_SEL-')],\ 149 | [sg.Text('J-Link Interface'),sg.Combo(jk_interface_list,jk_interface_list[0],size=(16,1),key='-JK_INTER-',pad=((0,3),(20,16)))],\ 150 | [sg.Text('RX Timout',pad=(10,20)),sg.InputText(rx_timeout,key='-RX_TIMEOUT-',size=(18,1),pad=((26,3),(20,16)),tooltip='0 means no timeout,Unit ms')],\ 151 | [sg.Text('J-Link S/N'),sg.InputText(sn,key='-SN-',pad=((24,3),(20,16)),size=(18,1))],\ 152 | [sg.Text('Speed(KHz)'), sg.InputText(jk_speed,pad=((14,3),(20,16)),key='-SPEED-',size=(18,1))],\ 153 | ] 154 | 155 | sd_bt_frame_layout = [[sg.Button('Send',key='-SD_DATA_BT-',pad=((45,28),(6,6)),size=(18,2),button_color=('grey0','grey100'),font=(font+str(12)))]] 156 | sd_data_frame_layout = [[sg.InputText('cmd:time syn',key='-SD_DATA_TXT-',size=(50,1),pad=((9,8),(10,15)),font=(font+str(20)),tooltip='Text type')]] 157 | 158 | layout = [[sg.Frame('Config', cfg_frame_layout, vertical_alignment='top',key='-CFG-'),\ 159 | sg.Multiline(autoscroll=True,key=RTT_DATA_WIN,size=(data_window_w,31),pad=(10,10),right_click_menu=right_click_menu,font=(font+font_size+' bold'),expand_x=True,expand_y=True)], 160 | [sg.Frame('Send data',sd_bt_frame_layout,vertical_alignment='top'), \ 161 | sg.Frame('Text Data',sd_data_frame_layout,vertical_alignment='top')], 162 | ] 163 | 164 | window = sg.Window('RTT Tool 1.5', layout,finalize=True,element_padding=(10,1),return_keyboard_events=False,icon=base64_main_icon,resizable=True) 165 | window.set_min_size(window.size) 166 | 167 | #window['-CFG-'].expand(True, True, True) 168 | window[RTT_DATA_WIN].expand(True, True, True) 169 | 170 | jlink_thread = JlinkThread(window,jlink) 171 | jlink_thread.start() 172 | 173 | mul_scroll_end = False 174 | real_time_save_file_name = False 175 | real_time_save_data = '' 176 | 177 | while True: 178 | event, values = window.read(timeout=200) 179 | 180 | if event == sg.WIN_CLOSED: 181 | jlink_thread.jlink_thread_ctr(False) 182 | jlink_reset(jlink) 183 | break 184 | 185 | #print(event, values) 186 | #Scroll bar in the middle position, as the data in the text box increases, y1 increases and y2 decreases 187 | y1, y2 = window[RTT_DATA_WIN].get_vscroll_position() 188 | if mul_scroll_end == True and bool(1 - y2): 189 | mul_scroll_end = False 190 | window[RTT_DATA_WIN].update(autoscroll=False) 191 | elif mul_scroll_end == False and y2 == 1: 192 | mul_scroll_end = True 193 | window[RTT_DATA_WIN].update(autoscroll=True) 194 | 195 | if event == '-JK_CONNECT-': 196 | if window['-JK_CONNECT-'].get_text() == 'Connect J-Link': 197 | jlink_op_suc = 0 198 | try: 199 | jlink.open() 200 | ser_num = jlink.serial_number 201 | jlink.close() 202 | except pylink.errors.JLinkException as e: 203 | sg.popup(e) 204 | jlink_op_suc = 1 205 | 206 | #J-Link reads S/N successfully 207 | if jlink_op_suc == 0: 208 | window['-SN-'].update(str(ser_num)) 209 | window[RTT_DATA_WIN].write('LOG:J-Link SN:'+str(ser_num)+'\n') 210 | try: 211 | jlink.open(str(ser_num)) 212 | #Set J-Link interface 213 | jk_interface = window['-JK_INTER-'].get() 214 | if jk_interface == 'SWD': 215 | jlink.set_tif(pylink.enums.JLinkInterfaces.SWD) 216 | 217 | window[RTT_DATA_WIN].write('LOG:J-Link interface:' + jk_interface + '\n') 218 | jlink.set_speed(int(window['-SPEED-'].get())) 219 | window[RTT_DATA_WIN].write('LOG:J-Link speed:' + window['-SPEED-'].get() + 'KHz''\n') 220 | #Connect J-Link 221 | jlink.connect(window['-CHIP_SEL-'].get()) 222 | #Set Reset I/O 223 | #jlink.set_reset_strategy(pylink.enums.JLinkResetStrategyCortexM3.RESETPIN) 224 | jlink.reset(ms=10, halt=False) 225 | #J-Link is connected 226 | if jlink.connected(): 227 | window['-DB_OUT-' + sg.WRITE_ONLY_KEY].write('LOG:J-Link connect success!\n') 228 | window['-JK_CONNECT-'].update(button_color=('grey0','green4')) 229 | window['-JK_CONNECT-'].update('Disconnect J-Link') 230 | 231 | #Check timeout time 232 | try: 233 | time_ms = int(window['-RX_TIMEOUT-'].get()) 234 | except: 235 | sg.popup('Receive timeout time is set incorrectly') 236 | time_ms = 0 237 | window['-RX_TIMEOUT-'].update('0') 238 | 239 | jlink_thread.gui_wakeup_tick_th = int(time_ms / (THREAD_RUN_INTERVAL_S * 10 ** 3)) 240 | #print('time_ms:', time_ms,jlink_thread.gui_wakeup_tick_th) 241 | window[RTT_DATA_WIN].write('LOG:RTT rx data timout:' + window['-RX_TIMEOUT-'].get() + '\n') 242 | 243 | if not jlink_thread.is_alive(): 244 | jlink_thread.start() 245 | jlink_thread.jlink_thread_ctr(True) 246 | 247 | jlink.rtt_start() 248 | window['-RX_TIMEOUT-'].update(disabled=True) 249 | window['-SN-'].update(disabled=True) 250 | window['-SPEED-'].update(disabled=True) 251 | except ValueError: 252 | logging.debug('Speed setting error') 253 | sg.popup('Speed setting error') 254 | jlink_reset(jlink) 255 | except Exception as e: 256 | logging.debug('J-Link Operation error[' + str(e) + ']') 257 | sg.popup('J-Link Operation error[' + str(e) + ']') 258 | jlink_reset(jlink) 259 | else: 260 | #Thread stop 261 | jlink_thread.jlink_thread_ctr(False) 262 | jlink_reset(jlink) 263 | window[RTT_DATA_WIN].write('LOG:J-Link disconnect!\n') 264 | window['-JK_CONNECT-'].update(button_color=('grey0', 'grey100')) 265 | window['-JK_CONNECT-'].update('Connect J-Link') 266 | window['-RX_TIMEOUT-'].update(disabled=False) 267 | window['-SN-'].update(disabled=False) 268 | window['-SPEED-'].update(disabled=False) 269 | 270 | elif event == 'Clear': 271 | window['-DB_OUT-' + sg.WRITE_ONLY_KEY].update('') 272 | 273 | elif event == '-TIMESTAMP_CTR-': 274 | if window['-TIMESTAMP_CTR-'].get_text() == 'Open Timestamp': 275 | window['-TIMESTAMP_CTR-'].update(button_color=('grey0', 'green4')) 276 | window['-TIMESTAMP_CTR-'].update('Close Timestamp') 277 | jlink_thread.jlink_timestamp_set(True) 278 | else: 279 | window['-TIMESTAMP_CTR-'].update(button_color=('grey0', 'grey100')) 280 | window['-TIMESTAMP_CTR-'].update('Open Timestamp') 281 | jlink_thread.jlink_timestamp_set(False) 282 | 283 | elif event == 'Scroll to the end': 284 | mul_scroll_end = True 285 | window['-DB_OUT-' + sg.WRITE_ONLY_KEY].update(autoscroll=True) 286 | 287 | elif event == '-DATA_SAVE-': 288 | file_name = r'log_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt' 289 | rtt_data_str = re.sub('(\r\n)+','\n',window[RTT_DATA_WIN].get()) 290 | #file_name = os.path.dirname(os.path.realpath(sys.argv[0])) + '\\log\\' + file_name 291 | #print(file_name) 292 | with open(file_name, 'w', encoding='utf-8') as f: 293 | f.write(rtt_data_str) 294 | sg.popup_no_wait('File saved successfully') 295 | 296 | elif event == '-RT_DATA_SAVE-': 297 | if window['-RT_DATA_SAVE-'].get_text() == 'Open Real-time saving data': 298 | window['-RT_DATA_SAVE-'].update(button_color=('grey0','green4')) 299 | window['-RT_DATA_SAVE-'].update('Close Real-time saving data') 300 | real_time_save_file_name = r'real_time_log_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt' 301 | else: 302 | window['-RT_DATA_SAVE-'].update(button_color=('grey0', 'grey100')) 303 | window['-RT_DATA_SAVE-'].update('Open Real-time saving data') 304 | 305 | elif event == '__TIMEOUT__': 306 | if len(real_time_save_data) > 0: 307 | try: 308 | with open(real_time_save_file_name, 'a', encoding='utf-8') as f: 309 | f.write(real_time_save_data) 310 | real_time_save_data = '' 311 | except Exception as e: 312 | logging.debug('Write real time data to file error[' + str(e) + ']\n') 313 | except: 314 | logging.debug('Write real time data to file error') 315 | sg.Print("Write real time data to file error") 316 | 317 | elif event == '-JLINK_READ_DATA_THREAD-': 318 | if values['-JLINK_READ_DATA_THREAD-'] != 'J-Link connect lost': 319 | window['-DB_OUT-' + sg.WRITE_ONLY_KEY].write(values['-JLINK_READ_DATA_THREAD-']) 320 | if window['-RT_DATA_SAVE-'].get_text() == 'Close Real-time saving data': 321 | real_time_save_data = real_time_save_data + re.sub('(\r\n)+','\n',values['-JLINK_READ_DATA_THREAD-']) 322 | else: 323 | logging.debug('J-Link connect lost') 324 | jlink_reset(jlink) 325 | jlink_thread.jlink_thread_ctr(False) 326 | window['-DB_OUT-' + sg.WRITE_ONLY_KEY].write('LOG:J-Link connection has been lost' + '\n') 327 | window['-JK_CONNECT-'].update(button_color=('grey0', 'grey100')) 328 | window['-JK_CONNECT-'].update('Connect J-Link') 329 | window['-RX_TIMEOUT-'].update(disabled=False) 330 | window['-SN-'].update(disabled=False) 331 | window['-SPEED-'].update(disabled=False) 332 | 333 | elif event == '-SD_DATA_BT-': 334 | data_cmd = window['-SD_DATA_TXT-'].get() 335 | if data_cmd.startswith('cmd:'): 336 | if data_cmd.find('time syn') >= 0: 337 | if jlink.opened(): 338 | try: 339 | time_str = 'time syn:' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') 340 | time_list = [ord(i) for i in time_str] 341 | jlink.rtt_write(0,time_list) 342 | logging.debug('Data send success(cmd:time syn):'+ time_str) 343 | except Exception as e: 344 | logging.debug('Data send failt(cmd:time syn)[' + str(e) + ']\n') 345 | except: 346 | logging.debug('Data send failt(cmd:time syn)') 347 | else: 348 | if jlink.opened(): 349 | try: 350 | time_list = [ord(i) for i in data_cmd] 351 | jlink.rtt_write(0, time_list) 352 | logging.debug('Data send success:' + data_cmd) 353 | except Exception as e: 354 | logging.debug('Data send error[' + str(e) + ']\n') 355 | except: 356 | logging.debug('Data send error') 357 | pass 358 | 359 | window.close() 360 | 361 | if __name__ == '__main__': 362 | main() 363 | -------------------------------------------------------------------------------- /main.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | 3 | 4 | block_cipher = None 5 | 6 | 7 | a = Analysis(['main.py'], 8 | pathex=[], 9 | binaries=[], 10 | datas=[], 11 | hiddenimports=[], 12 | hookspath=[], 13 | hooksconfig={}, 14 | runtime_hooks=[], 15 | excludes=[], 16 | win_no_prefer_redirects=False, 17 | win_private_assemblies=False, 18 | cipher=block_cipher, 19 | noarchive=False) 20 | pyz = PYZ(a.pure, a.zipped_data, 21 | cipher=block_cipher) 22 | 23 | exe = EXE(pyz, 24 | a.scripts, 25 | a.binaries, 26 | a.zipfiles, 27 | a.datas, 28 | [], 29 | name='main', 30 | debug=False, 31 | bootloader_ignore_signals=False, 32 | strip=False, 33 | upx=True, 34 | upx_exclude=[], 35 | runtime_tmpdir=None, 36 | console=False, 37 | disable_windowed_traceback=False, 38 | target_arch=None, 39 | codesign_identity=None, 40 | entitlements_file=None , icon='apple.ico') 41 | -------------------------------------------------------------------------------- /rtt-t.log: -------------------------------------------------------------------------------- 1 | 2022/01/23 05:42:14 ---------------------------------------------------------------- 2 | 2022/01/23 05:42:14 ---------------------------------------------------------------- 3 | 2022/01/23 05:42:14 ---------------RTT-T Debug Log--------------- 4 | 2022/01/23 05:42:14 ---------------------------------------------------------------- 5 | 2022/01/23 05:42:14 ---------------------------------------------------------------- 6 | 2022/01/23 05:42:15 Thread:rtt data length [0] 7 | 2022/01/23 05:42:15 Thread:rtt data [] 8 | 2022/01/23 05:42:15 Thread:GUI wakeup tick threshold 0 9 | 2022/01/23 05:42:15 Thread:J-Link thread wait...... 10 | 2022/01/23 05:42:17 Thread:J-Link thread disble 11 | -------------------------------------------------------------------------------- /windows icon update.bat: -------------------------------------------------------------------------------- 1 | 2 | rem 关闭Windows外壳程序explorer 3 | taskkill /f /im explorer.exe 4 | rem 清理系统图标缓存数据库 5 | attrib -h -s -r "%userprofile%\AppData\Local\IconCache.db" 6 | del /f "%userprofile%\AppData\Local\IconCache.db" 7 | attrib /s /d -h -s -r "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\*" 8 | del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_32.db" 9 | del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_96.db" 10 | del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_102.db" 11 | del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_256.db" 12 | del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_1024.db" 13 | del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_idx.db" 14 | del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_sr.db" 15 | rem 清理 系统托盘记忆的图标 16 | echo y|reg delete "HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify" /v IconStreams 17 | echo y|reg delete "HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify" /v PastIconsStream 18 | rem 重启Windows外壳程序explorer 19 | start explorer 20 | ———————————————— 21 | 版权声明:本文为CSDN博主「Vvlowkey」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 22 | 原文链接:https://blog.csdn.net/vvlowkey/article/details/51133486 --------------------------------------------------------------------------------