├── ip_uds_bl.sln ├── ip_uds_bl.suo └── ip_uds_bl ├── SRecord.py ├── UnmanagedCode.dll ├── can_if.py ├── can_tp.py ├── gm3110.py ├── ip_uds_bl.py ├── ip_uds_bl.pyproj ├── myutils.py ├── uds.py ├── vxlapi.dll ├── vxlapi64.dll └── vxlapi_NET20.dll /ip_uds_bl.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "ip_uds_bl", "ip_uds_bl\ip_uds_bl.pyproj", "{3BD7605F-68EF-4246-A07D-3E13BA88D8AF}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {3BD7605F-68EF-4246-A07D-3E13BA88D8AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {3BD7605F-68EF-4246-A07D-3E13BA88D8AF}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(SolutionProperties) = preSolution 16 | HideSolutionNode = FALSE 17 | EndGlobalSection 18 | EndGlobal 19 | -------------------------------------------------------------------------------- /ip_uds_bl.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satish77/ip_uds_bl_tool/1a221301a35e0ec8a099bf92e4e2affb92aae91b/ip_uds_bl.suo -------------------------------------------------------------------------------- /ip_uds_bl/SRecord.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2011 Satish Krosuru 3 | 4 | from struct import * 5 | from array import * 6 | import sys 7 | import time 8 | import myutils 9 | import operator 10 | 11 | g_prg_rqst = 0 12 | 13 | class SRecord: 14 | def __init__(self, init=0xff, checkcs=True): 15 | self.udata = [] 16 | self.data = [] 17 | self.tail = {} 18 | self.offset = 0 19 | self.size = 0 20 | self.start = None 21 | self.comm = [] 22 | self.init = init 23 | self.check = checkcs 24 | 25 | def get_data(self): 26 | return self.udata 27 | 28 | def readrecord(self, line): 29 | """Read a line and give an S-Record address, data and checksum""" 30 | type = line[:2] 31 | data = [int(line[i:i + 2], 16) for i in range(2, len(line), 2)] 32 | cs = (reduce(operator.add, data) + 1) & 0xff 33 | if type in ('S1', 'S9'): 34 | adr = (data[1] << 8) + data[2] 35 | fd = 3 36 | elif type in ('S2', 'S8'): 37 | adr = (data[1] << 16) + (data[2] << 8) + data[3] 38 | fd = 4 39 | elif type in ('S3', 'S7'): 40 | adr = (long(data[1]) << 24) + (data[2] << 16) + (data[3] << 8) + data[4] 41 | fd = 5 42 | elif type == 'S0': # Comment 43 | return 'C', 0, data[3:-1], cs 44 | else: 45 | raise ValueError, "Not a valid S-Record" 46 | if type > 'S6': # Start Address 47 | type = 'S' 48 | else: # Data 49 | type = 'D' 50 | return type, adr, data[fd:-1], cs 51 | 52 | def readrecords(self, records): 53 | """A list (rows) of S-Records read.""" 54 | recno = -1 55 | for line in records: 56 | recno += 1 57 | line = line.rstrip() 58 | type, adr, data, cs = self.readrecord(line) 59 | if cs and self.checkcs: 60 | raise ValueError, "Error in Record %d" % recno 61 | if type == 'D': 62 | ## if recno < 10: 63 | ## print hex(adr) + "\t" + line 64 | self.udata.append((adr, data)) 65 | elif type == 'S': 66 | #print "Starting address: " + hex(adr) 67 | self.start = adr 68 | else: 69 | self.comm.append("".join(map(chr, data))) 70 | if not self.udata: 71 | return 72 | self.udata.sort() 73 | #print self.udata[0] 74 | loadr = self.udata[0][0] 75 | hiadr = self.udata[-1][0] + len(self.udata[-1][1]) 76 | size = hiadr - loadr 77 | #print "loadr:" + str(hex(loadr)) + "\thiadr:" + str(hex(hiadr)) + "\tsize(KB):" + str(size/1024) 78 | 79 | def print_chunks(self): 80 | udata_len = len(self.udata) 81 | i = 0 82 | next_addr = 0 83 | chunk_size = 0 84 | chunk_addr = 0 85 | num_chunks = 0 86 | for i in range(0, udata_len): 87 | #if num_chunks < 10: 88 | # print "Address:" + hex(self.udata[i][0]) + "\tLength:" + str(len(self.udata[i][1])) 89 | if self.udata[i][0] == next_addr: 90 | chunk_size += len(self.udata[i][1]) 91 | next_addr += len(self.udata[i][1]) 92 | else: 93 | if chunk_size > 0: 94 | num_chunks = num_chunks + 1 95 | #if num_chunks < 10: 96 | print "Chunk address: 0x%08X" % chunk_addr + "\tSize(bytes): %8d" % chunk_size 97 | chunk_size = len(self.udata[i][1]) 98 | chunk_addr = self.udata[i][0] 99 | next_addr = self.udata[i][0] + len(self.udata[i][1]) 100 | if chunk_size > 0: 101 | num_chunks = num_chunks + 1 102 | print "Chunk address: 0x%08X" % chunk_addr + "\tSize(bytes): %8d" % chunk_size 103 | 104 | def send_to_target(self, addr, buf): 105 | global g_prg_rqst 106 | 107 | ## if g_prg_rqst > 3: 108 | ## return 109 | 110 | g_prg_rqst = g_prg_rqst + 1 111 | assert ((addr & 0x7) == 0) 112 | assert ((len(buf) & 0x7) == 0) 113 | if buf == []: 114 | print "Empty" 115 | else: 116 | a = ' '.join( [ "%02X" % x for x in buf ]) 117 | #print "0x%08X" % addr, len(buf), map(hex, buf) 118 | #print "0x%08X" % addr, "%2X" % len(buf), a 119 | print "%5d" % g_prg_rqst, "%08X" % addr, "%2X" % len(buf) 120 | 121 | a = [] 122 | a.append((addr >> 24) & 0xFF) 123 | a.append((addr >> 16) & 0xFF) 124 | a.append((addr >> 8) & 0xFF) 125 | a.append(addr & 0xFF) 126 | a.append((len(buf) >> 8) & 0xFF) 127 | a.append(len(buf) & 0xFF) 128 | a = a + buf 129 | print a 130 | #self.WriteArray("fprgBuff", a, len(a)) 131 | #self.WriteVariable("fprgCSW", 0x8B) 132 | 133 | def download_to_target(self): 134 | global g_prg_rqst 135 | buf = [] 136 | buf_max = 32 137 | buf_addr = 0 138 | g_prg_rqst = 0 139 | for i in range(len(self.udata)): 140 | sr_addr = self.udata[i][0] 141 | """ if buffer is empty then record s-record as start address of the buffer and next data address""" 142 | if buf == []: 143 | sr_addr_aligned = sr_addr & 0xFFFFFFF8 144 | buf_addr = next_data_addr = sr_addr_aligned 145 | """ pad for non-aligned addresses """ 146 | for l in range(sr_addr_aligned, sr_addr): 147 | buf.append(0xFF) 148 | next_data_addr = next_data_addr + 1 149 | elif next_data_addr != sr_addr: 150 | buf_end_addr_aligned = (buf_addr + len(buf) + 7 - 1) & ~7 151 | if(sr_addr > buf_end_addr_aligned): 152 | while (next_data_addr % 8) != 0: 153 | buf.append(0xFF) 154 | next_data_addr = next_data_addr + 1 155 | self.send_to_target(buf_addr, buf) 156 | buf = [] 157 | buf_addr = next_data_addr = sr_addr 158 | assert (buf_addr & 0x7) == 0 159 | else: 160 | while(next_data_addr < sr_addr): 161 | buf.append(0xFF) 162 | next_data_addr = next_data_addr + 1 163 | 164 | if len(buf) >= buf_max: 165 | self.send_to_target(buf_addr, buf) 166 | buf_addr = next_data_addr 167 | assert (buf_addr & 0x7) == 0 168 | buf = [] 169 | 170 | for j in range(len(self.udata[i][1])): 171 | data = self.udata[i][1][j] 172 | buf.append(data) 173 | next_data_addr = next_data_addr + 1 174 | if len(buf) >= buf_max: 175 | self.send_to_target(buf_addr, buf) 176 | buf_addr = next_data_addr 177 | assert (buf_addr & 0x7) == 0 178 | buf = [] 179 | """ if buffer is not algined then pad it """ 180 | while((len(buf) % 8) <> 0): 181 | buf.append(0xFF) 182 | self.send_to_target(buf_addr, buf) 183 | 184 | if __name__ == '__main__': 185 | pass 186 | #s19path = win32api.GetFullPathName(sys.argv[1]) 187 | 188 | #print "s19 file " + s19path 189 | #if (len(win32api.FindFiles(s19path)) == 0): 190 | # print "Please give correct s19 file." 191 | # sys.exit(0) 192 | 193 | #start_time = time.time() 194 | #temp_time = time.localtime() 195 | #str_date = str(temp_time[1]) + ":"+ str(temp_time[2]) + ":" + str(temp_time[0]) 196 | #str_time = str(temp_time[3]) + ":"+ str(temp_time[4]) + ":" + str(temp_time[5]) 197 | #print "Start Date [MM:DD:YYYY] " + str_date 198 | #print "Start Time [HH:MM:SS] " + str_time 199 | #fp = open(s19path, 'rb') 200 | #rcount = 0 201 | #data = fp.readlines() 202 | #s = SRecord() 203 | #s.readrecords(data) 204 | #fp.close() 205 | #end_time = time.time() 206 | #temp_time = time.localtime() 207 | #str_time = str(temp_time[3]) + ":"+str(temp_time[4]) + ":" + str(temp_time[5]) 208 | #print "End Time [HH:MM:SS] " + str_time 209 | #s.print_chunks() 210 | #s.download_to_target() 211 | #time_taken = (time.time() - start_time) 212 | #print "Time Taken: " + str(time_taken) + ( "Seconds") 213 | 214 | #print "Finished ..." 215 | 216 | -------------------------------------------------------------------------------- /ip_uds_bl/UnmanagedCode.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satish77/ip_uds_bl_tool/1a221301a35e0ec8a099bf92e4e2affb92aae91b/ip_uds_bl/UnmanagedCode.dll -------------------------------------------------------------------------------- /ip_uds_bl/can_if.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import System 3 | import clr 4 | clr.AddReferenceToFile("vxlapi_NET20.dll") 5 | import vxlapi_NET20 6 | clr.AddReferenceToFile("UnmanagedCode.dll") 7 | import UnmanagedCode 8 | import myutils 9 | 10 | 11 | class CanIf: 12 | def __init__(self): 13 | self.cmd_id = 0x222 14 | self.rsp_id = 0x111 15 | self.timeout = 0 16 | self.rx_thread_active = True 17 | 18 | try: 19 | self.rxChannel = vxlapi_NET20.xlSingleChannelCAN_Port("py_canif", 0) 20 | self.txChannel = vxlapi_NET20.xlSingleChannelCAN_Port("py_canif", 0) 21 | 22 | if(self.txChannel.xlCheckPort() and self.rxChannel.xlCheckPort()): 23 | self.txChannel.xlPrintConfig(); 24 | self.rxChannel.xlPrintConfig(); 25 | 26 | self.rxChannel.xlResetAcceptanceFilter() 27 | self.rxChannel.xlCanAddAcceptanceRange(self.rsp_id, self.rsp_id) 28 | 29 | self.txChannel.xlActivate() 30 | self.rxChannel.xlActivate() 31 | 32 | self.rxThread = System.Threading.Thread(System.Threading.ThreadStart(self.rx_thread)) 33 | self.rxThread.Start() 34 | 35 | self.event_sink = None 36 | 37 | except: 38 | print "Exception occurred!!!" 39 | print sys.exc_info()[0], sys.exc_info()[1] 40 | #sys.exit(1) 41 | 42 | def xmit(self, list): 43 | if(len(list) > 0): 44 | data = 0 45 | for i in range(len(list)): 46 | data = (list[i] << (i*8)) | data 47 | if (myutils.debug_switch & myutils.can_msg_trace) != 0: 48 | print "%016X\n" % data 49 | self.txChannel.xlTransmit(self.cmd_id, len(list), data) 50 | 51 | def rx_thread(self): 52 | WaitResults = dict( 53 | WAIT_OBJECT_0 = 0x0, 54 | WAIT_ABANDONED = 0x80, 55 | WAIT_TIMEOUT = 0x102, 56 | INFINITE = 0xFFFF, 57 | WAIT_FAILED = 0xFFFFFFF) 58 | 59 | System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest 60 | 61 | xld = vxlapi_NET20.XLDriver() 62 | print xld.XL_ResetClock(1) 63 | 64 | #raw_input("press any key..") 65 | 66 | """ three second timer - resolution is 10 us""" 67 | #xld.XL_SetTimerRate(0, 300000) 68 | 69 | receivedEvent = vxlapi_NET20.XLClass.xl_event() 70 | xlStatus = vxlapi_NET20.XLClass.XLstatus.XL_SUCCESS 71 | 72 | while self.rx_thread_active: 73 | #waitResult = UnmanagedCode.Kernel32.WaitForSingleObject(self.rxChannel.eventHandle, WaitResults.get('INFINITE')) 74 | """ wait for the event for 10 ms """ 75 | waitResult = UnmanagedCode.Kernel32.WaitForSingleObject(self.rxChannel.eventHandle, 10) 76 | if waitResult == WaitResults.get('WAIT_TIMEOUT'): 77 | self.timeout = 1 78 | else: 79 | self.timeout = 0 80 | xlStatus = self.rxChannel.xlReceive(receivedEvent) 81 | while xlStatus[0] != vxlapi_NET20.XLClass.XLstatus.XL_ERR_QUEUE_IS_EMPTY: 82 | #while xlStatus[0] == vxlapi_NET20.XLClass.XLstatus.XL_SUCCESS: 83 | #print("received event") 84 | #print xlStatus 85 | #print int(vxlapi_NET20.XLClass.XLeventType.XL_RECEIVE_MSG) 86 | if xlStatus[1].tag == 1: 87 | #print 'XL_RECEIVE_MSG' 88 | if (myutils.debug_switch & myutils.can_msg_trace) != 0: 89 | self.rxChannel.xlPrintRx(xlStatus[1]) 90 | 91 | # print the received message 92 | #print 'id: 0x%02x' % xlStatus[1].tagData.can_Msg.id 93 | #print 'dlc: ', xlStatus[1].tagData.can_Msg.dlc 94 | #print 'data: ', 95 | #for md in xlStatus[1].tagData.can_Msg.data: 96 | # print ' %02x' % md, 97 | #print 98 | #print 'flags: 0x%02x' % xlStatus[1].tagData.can_Msg.flags 99 | 100 | if xlStatus[1].tagData.can_Msg.id == self.rsp_id: 101 | self.rsp_received = 1 102 | 103 | # convert from byte array to a string 104 | self.received_data = [] 105 | for d in xlStatus[1].tagData.can_Msg.data: 106 | self.received_data += [int(d)] 107 | 108 | if self.received_data[0] <> 0xFF: 109 | self.cmd_failed = 1 110 | else: 111 | self.cmd_failed = 0 112 | 113 | if self.event_sink <> None: 114 | self.event_sink() 115 | 116 | elif xlStatus[1].tag == 4: 117 | print 'XL_CHIP_STATE' 118 | elif xlStatus[1].tag == 6: 119 | print 'XL_TRANSCEIVER' 120 | elif xlStatus[1].tag == 8: 121 | print 'XL_TIMER' 122 | elif xlStatus[1].tag == 10: 123 | print 'XL_TRANSMIT_MSG' 124 | elif xlStatus[1].tag == 11: 125 | print 'XL_SYNC_PULSE' 126 | elif xlStatus[1].tag == 15: 127 | print 'XL_APPLICATION_NOTIFICATION' 128 | else: 129 | print "Unknown tag: " + str(xlStatus[1].tag) 130 | 131 | #if xlStatus[1].tag == vxlapi_NET20.XLClass.XLeventType.XL_RECEIVE_MSG: 132 | # print 'vxlapi_NET20.XLClass.XLeventType.XL_RECEIVE_MSG' 133 | #elif xlStatus[1].tag == vxlapi_NET20.XLClass.XLeventType.XL_CHIP_STATE: 134 | # print 'vxlapi_NET20.XLClass.XLeventType.XL_CHIP_STATE' 135 | #elif xlStatus[1].tag == vxlapi_NET20.XLClass.XLeventType.XL_TRANSCEIVER: 136 | # print 'vxlapi_NET20.XLClass.XLeventType.XL_TRANSCEIVER' 137 | #elif xlStatus[1].tag == vxlapi_NET20.XLClass.XLeventType.XL_TIMER: 138 | # print 'vxlapi_NET20.XLClass.XLeventType.XL_TIMER' 139 | #elif xlStatus[1].tag == vxlapi_NET20.XLClass.XLeventType.XL_TRANSMIT_MSG: 140 | # print 'vxlapi_NET20.XLClass.XLeventType.XL_TRANSMIT_MSG' 141 | #elif xlStatus[1].tag == vxlapi_NET20.XLClass.XLeventType.XL_SYNC_PULSE: 142 | # print 'vxlapi_NET20.XLClass.XLeventType.XL_SYNC_PULSE' 143 | 144 | 145 | xlStatus = self.rxChannel.xlReceive(receivedEvent) 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /ip_uds_bl/can_tp.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import myutils 3 | #import System.Timers 4 | import threading 5 | import time 6 | 7 | class CanTp(object): 8 | def __init__(self, canif): 9 | self.Init() 10 | self.event_sink = None 11 | canif.event_sink = self.on_receive 12 | self.canif = canif 13 | self.timedout = False 14 | 15 | def Init(self): 16 | self.data_out = [] 17 | self.data_in = [] 18 | self.seq_ctr = 0 19 | self.first_frame_rcvd = False 20 | self.first_frame_sent = False 21 | 22 | def AppendData(self, data): 23 | #a = ' '.join( [ "%02X" % x for x in data ]) 24 | #print a 25 | self.data_out.extend(data) 26 | 27 | def DecodeFrame(self, data_bytes): 28 | process_data = False 29 | frame_type = data_bytes[0] >> 4 30 | if frame_type == 0: # single frame 31 | self.data_in_dl = data_bytes[0] & 0xF 32 | self.data_in.extend(data_bytes[1:self.data_in_dl+1]) 33 | process_data = True 34 | elif frame_type == 1: # first frame 35 | if frame_type == 1: 36 | self.data_in_dl = ((data_bytes[0] & 0xF) << 8) | data_bytes[1] 37 | self.data_in.extend(data_bytes[2:self.data_in_dl+2]) 38 | self.first_frame_rcvd = 1 39 | self.exp_seq_ctr = 1 40 | elif frame_type == 2 and self.first_frame_rcvd == 1: # consecutive frame 41 | seq_ctr = data_bytes[0] & 0xF 42 | if seq_ctr <> self.exp_seq_ctr: 43 | self.first_frame_rcvd = 0 44 | else: 45 | self.data_in.extend(data_bytes[1:8]) 46 | while(len(self.data_in) > self.data_in_dl): 47 | # delete any excess data appended 48 | self.data_in.pop() 49 | process_data = True 50 | self.exp_seq_ctr = (self.exp_seq_ctr + 1) % 16 51 | elif frame_type == 3: # flow control frame 52 | self.data_out_BS = data_bytes[1] 53 | self.data_out_STMin = data_bytes[2] 54 | else: 55 | pass 56 | return(process_data) 57 | 58 | """ TODO: Handle more than 4095 bytes of data """ 59 | def EncodeFrame(self): 60 | data_bytes = [] 61 | if len(self.data_out) > 0: 62 | if self.first_frame_sent == True: 63 | self.seq_ctr = (self.seq_ctr + 1) % 16 64 | data_bytes.append((2 << 4) | self.seq_ctr) 65 | data_bytes.extend(self.data_out[:7]) 66 | self.data_out = self.data_out[7:] 67 | else: 68 | if len(self.data_out) <= 7: 69 | # single frame 70 | data_bytes.append(len(self.data_out)) 71 | data_bytes.extend(self.data_out) 72 | self.data_out = [] 73 | else: 74 | # first frame 75 | data_bytes.append((1 << 4) | (len(self.data_out) >> 8)) 76 | data_bytes.append(len(self.data_out) & 0xFF) 77 | data_bytes.extend(self.data_out[:6]) 78 | self.data_out = self.data_out[6:] 79 | self.seq_ctr = 0 80 | self.first_frame_sent = True 81 | return(data_bytes) 82 | 83 | def xmit(self, list): 84 | if myutils.debug_switch & 0x2 <> 0: 85 | for item in list: print '%02X' % int(item), 86 | print 87 | self.data_out = list 88 | self.active = True 89 | self.t = threading.Timer(0.1, self.TaskThread) # 100 ms 90 | self.t.start() 91 | #self.t.join() 92 | #self.Task() 93 | 94 | def on_receive(self): 95 | myutils.debug_print(myutils.program_trace, "CanTp::on_receive") 96 | if self.canif.received_data[0] <> 0x30: 97 | if self.DecodeFrame(self.canif.received_data) == True: 98 | if self.event_sink <> None: 99 | self.event_sink() 100 | else: 101 | myutils.debug_print(myutils.can_msg_trace, 'Flow control frame received.') 102 | 103 | def TaskThread(self): 104 | myutils.debug_print(myutils.program_trace, "CanTp::TaskThread") 105 | self.active = True 106 | start = time.clock() 107 | while self.active == True: 108 | if (time.clock()-start) > 0.001: # 1 ms 109 | start = time.clock() 110 | can_data_bytes = self.EncodeFrame() 111 | if len(can_data_bytes) > 0: 112 | self.canif.xmit(can_data_bytes) 113 | self.timedout = False 114 | else: 115 | self.active = False 116 | #print self.timedout, self.active 117 | 118 | 119 | def Task(self): 120 | #myutils.debug_print(myutils.program_trace, "CanTp::Task") 121 | if self.active == True: 122 | can_data_bytes = self.EncodeFrame() 123 | if len(can_data_bytes) > 0: 124 | self.canif.xmit(can_data_bytes) 125 | self.timedout = False 126 | # Method 1: Not working 127 | # self.t = System.Timers.Timer(0.100) 128 | # self.t.Elapsed += self.on_timeout 129 | # Method 2: Not working 130 | # timer = Timer() 131 | # timer.Interval = 6000 132 | # timer.Tick += self.on_timeout 133 | # timer.Start() 134 | # timer_id = timer.set_timer(1000, self.on_timeout) 135 | #self.t = threading.Timer(0.05, self.on_stmin_tout) # 50 ms 136 | self.t = threading.Timer(0.1, self.on_stmin_tout) # 100 ms 137 | self.t.start() 138 | #self.t.join() 139 | else: 140 | self.active = False 141 | #print self.timedout, self.active 142 | return self.active 143 | 144 | def on_stmin_tout(self): 145 | self.t.cancel() 146 | self.Task() 147 | 148 | 149 | class CanTpTestSuite(unittest.TestCase): 150 | def setUp(self): 151 | self.ct = NewCanTp() 152 | 153 | """Verify receive of single frame""" 154 | def test1(self): 155 | self.ct.Init() 156 | self.ct.DecodeFrame([0x5, 1, 2, 3, 4, 5, 6, 7]) 157 | self.assertEqual(self.ct.data_in, [1, 2, 3, 4, 5], 'Single frame test') 158 | 159 | """Verify receive of multiple frames""" 160 | def test2(self): 161 | self.ct.Init() 162 | self.ct.DecodeFrame([0x10, 0xF, 1, 2, 3, 4, 5, 6]) 163 | self.ct.DecodeFrame([0x21, 7, 8, 9, 0xA, 0xB, 0xC, 0xD]) 164 | self.ct.DecodeFrame([0x22, 0xE, 0xF, 1, 2, 3]) 165 | self.assertEqual(self.ct.data_in, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF]) 166 | 167 | """Verify transmit of single frame""" 168 | def test3(self): 169 | self.ct.Init() 170 | self.ct.data_out = [1, 2, 3, 4, 5, 6, 7] 171 | self.assertEqual(self.ct.EncodeFrame(), [0x7, 1, 2, 3, 4, 5, 6, 7]) 172 | 173 | """Verify transmit of multiple frames""" 174 | def test4(self): 175 | self.ct.Init() 176 | self.ct.data_out = [1, 2, 3, 4, 5, 6, 7, 8] 177 | self.assertEqual(self.ct.EncodeFrame(), [0x10, 8, 1, 2, 3, 4, 5, 6]) 178 | self.assertEqual(self.ct.EncodeFrame(), [0x21, 7, 8]) 179 | 180 | if __name__ == '__main__': 181 | unittest.main(exit=False) 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /ip_uds_bl/gm3110.py: -------------------------------------------------------------------------------- 1 | class GM3110: 2 | def __init__(self): 3 | self.cantp = can_tp.CanTp() 4 | self.can_tx_rdy = True 5 | self.active = False 6 | 7 | def sm(self): 8 | debug_print(1, "UDS State Machine") 9 | # TODO: set can_tx_rdy to True after STMIN and after sending previous message 10 | if self.can_tx_rdy and self.active == True: 11 | can_data_bytes = self.cantp.EncodeFrame() 12 | if len(can_data_bytes) > 0: 13 | can_xmit(can_data_bytes) 14 | else: 15 | self.active = False 16 | 17 | """ Transfers at the most 4095 bytes of data """ 18 | def TransferAndGo(self, address, data, go=False): 19 | debug_print(1, "TransferAndGo") 20 | self.cantp.Init() 21 | uds_header = [0x36] 22 | if go == True: 23 | uds_header.append(0x80) 24 | else: 25 | uds_header.append(0x00) 26 | self.cantp.AppendData(uds_header) 27 | self.cantp.AppendData(long_to_list(address)) 28 | self.cantp.AppendData(data) 29 | self.active = True 30 | while self.active == True: self.sm() 31 | 32 | def RequestForDownload(self): 33 | debug_print(1, "RequestForDownload") 34 | uds_header = [0x34] 35 | self.cantp.Init() 36 | self.cantp.AppendData(uds_header) 37 | self.active = True 38 | while self.active == True: self.sm() 39 | -------------------------------------------------------------------------------- /ip_uds_bl/ip_uds_bl.py: -------------------------------------------------------------------------------- 1 | import SRecord 2 | import can_if 3 | import can_tp 4 | import uds 5 | import myutils 6 | import System.Timers 7 | import random 8 | import System.DateTime 9 | 10 | flash_sec_addr = [ 11 | 0xA0000000, 12 | 0xA0004000, 13 | 0xA0008000, 14 | 0xA000C000, 15 | 0xA0010000, 16 | 0xA0014000, 17 | 0xA0018000, 18 | 0xA001C000, 19 | 0xA0020000, 20 | 0xA0028000, 21 | 0xA0030000, 22 | 0xA0038000, 23 | 0xA0040000, 24 | 0xA0048000, 25 | 0xA0050000, 26 | 0xA0058000, 27 | 0xA0060000, 28 | 0xA0070000, 29 | 0xA0080000, 30 | 0xA0090000, 31 | 0xA00A0000, 32 | 0xA00C0000, 33 | 0xA00E0000, 34 | 0xA0100000, 35 | 0xA0140000, 36 | 0xA0180000, 37 | 0xA01C0000 38 | ] 39 | 40 | class MainClass: 41 | def __init__(self, uds): 42 | self.states = { 'IDLE' : 0, 43 | 'START' : 1, 44 | 'UDS_TRANSFER_DATA' : 2, 45 | 'UDS_TRANSFER_EXIT' : 3, 46 | 'UDS_REQUEST_DOWNLOAD' : 4, 47 | 'UDS_ERASE_MEMORY' : 5 } 48 | self.state = self.states['IDLE'] 49 | self.uds = uds 50 | self.uds.event_sink = self.on_rcv_data 51 | 52 | def on_rcv_data(self): 53 | if self.state <> self.states['IDLE']: 54 | while self.Task(): 55 | pass 56 | 57 | def DownloadS19(self, s19filename): 58 | """ Download S-Record file """ 59 | s19file = open(s19filename) 60 | lines = s19file.readlines() 61 | s19file.close() 62 | self.sr = SRecord.SRecord() 63 | self.sr.readrecords(lines) 64 | self.sr.print_chunks() 65 | data = self.sr.get_data() 66 | self.srec_idx = 0 67 | # chunk size is limited to 1024 bytes eventhough 4095 is the protocol limit. 68 | self.chunk_size = 1024 69 | self.state = self.states['UDS_REQUEST_DOWNLOAD'] 70 | self.uds.event_sink = self.on_rcv_data 71 | self.Task() 72 | 73 | def Task(self): 74 | assert self.state in self.states.values() 75 | 76 | continue_execution = False 77 | 78 | if self.state == self.states['UDS_REQUEST_DOWNLOAD']: 79 | self.uds.event_sink = self.on_rcv_data 80 | data = self.sr.get_data() 81 | assert self.srec_idx < len(data) 82 | self.uds_data = [] 83 | self.start_address = data[self.srec_idx][0] 84 | next_address = data[self.srec_idx][0] 85 | # concatenate all contiguous data 86 | while (self.srec_idx < len(data)) and (data[self.srec_idx][0] == next_address) and (len(self.uds_data) < (self.chunk_size*2)): 87 | self.uds_data.extend(data[self.srec_idx][1]) 88 | next_address = data[self.srec_idx][0] + len(data[self.srec_idx][1]) 89 | self.srec_idx = self.srec_idx + 1 90 | """ find out if the block contains non-zero elements """ 91 | is_zero = True 92 | for idx, byte in enumerate(self.uds_data): 93 | if byte <> 0: 94 | is_zero = False 95 | myutils.debug_print(myutils.debug_info, "Non-zero offset %d" % idx) 96 | break 97 | """ if length of block is non-zero, download the data """ 98 | if (len(self.uds_data) > 0): 99 | if not is_zero: 100 | self.uds.RequestDownload(self.start_address, len(self.uds_data)) 101 | self.chunk_idx = 0 102 | self.state = self.states['UDS_TRANSFER_DATA'] 103 | else: 104 | print 'Skipped zero block at address 0x%08x' % self.start_address 105 | if self.srec_idx < len(data): 106 | continue_execution = True 107 | else: 108 | self.state = self.states['IDLE'] 109 | else: 110 | self.state = self.states['IDLE'] 111 | elif self.state == self.states['UDS_TRANSFER_DATA']: 112 | print '0x%08x' % (self.start_address+self.chunk_idx) 113 | self.uds.TransferData(self.uds_data[self.chunk_idx:self.chunk_idx+self.chunk_size]) 114 | self.chunk_idx = self.chunk_idx + self.chunk_size 115 | if self.chunk_idx >= len(self.uds_data): 116 | self.state = self.states['UDS_TRANSFER_EXIT'] 117 | elif self.state == self.states['UDS_TRANSFER_EXIT']: 118 | self.uds.RequestTransferExit() 119 | data = self.sr.get_data() 120 | """ switch to IDLE state if no more records to download """ 121 | if self.srec_idx < len(data): 122 | self.state = self.states['UDS_REQUEST_DOWNLOAD'] 123 | else: 124 | self.state = self.states['IDLE'] 125 | #if (myutils.debug_switch & 0x8000) == 0x8000: # stop on first transfer 126 | # self.state = self.states['IDLE'] 127 | 128 | return(continue_execution) 129 | 130 | def EraseFlashBock(self, start_block_idx, num_blocks): 131 | self.uds.event_sink = self.EraseFlashBlockTask 132 | self.state = self.states['UDS_ERASE_MEMORY'] 133 | params = myutils.long_to_list(flash_sec_addr[start_block_idx]) 134 | params.append(num_blocks) 135 | self.uds.RoutineControl(uds.control_type['START'], uds.routines['ERASE_MEMORY'], params) 136 | 137 | def TransferSomeData(self, target_address, data): 138 | self.uds.event_sink = self.TransferDataTask 139 | self.uds_data = data 140 | self.state = self.states['UDS_TRANSFER_DATA'] 141 | self.uds.RequestDownload(target_address, len(data)) 142 | 143 | def TransferDataTask(self): 144 | if self.state == self.states['UDS_TRANSFER_DATA']: 145 | self.uds.TransferData(self.uds_data) 146 | self.state = self.states['UDS_TRANSFER_EXIT'] 147 | elif self.state == self.states['UDS_TRANSFER_EXIT']: 148 | self.uds.RequestTransferExit() 149 | self.state = self.states['IDLE'] 150 | 151 | def EraseFlashBlockTask(self): 152 | self.state = self.states['IDLE'] 153 | """ 154 | Steps:- 155 | 1. Download SBL 156 | 2. Erase App sectors 157 | 3. Download(Flash) App. 158 | """ 159 | 160 | canif = can_if.CanIf() 161 | cantp = can_tp.CanTp(canif) 162 | uds = uds.UDS(cantp) 163 | mc = MainClass(uds) 164 | 165 | states = { 166 | 'IDLE' : 0, 167 | 'DOWNLOAD_SBL': 1, 168 | 'ERASE_APP' : 2, 169 | 'DOWNLOAD_APP': 3 170 | } 171 | 172 | block_to_erase = 7 173 | last_block_to_erase = 22 174 | 175 | def main_func(): 176 | global state 177 | global block_to_erase 178 | global last_block_to_erase 179 | 180 | #while (mc.state <> mc.states['IDLE'] and (uds.timedout == False)): 181 | # pass 182 | #print 'mc.state', mc.state 183 | if mc.state == mc.states['IDLE']: 184 | #print 'state', state 185 | if state == states['DOWNLOAD_SBL']: 186 | mc.DownloadS19(r'C:\p\hgprojects\TC27XSBL\app\bin\AurixSBL.s19') 187 | state = states['ERASE_APP'] 188 | elif state == states['ERASE_APP']: 189 | if block_to_erase <= last_block_to_erase: 190 | print "Erasing Flash Sector: %d" % block_to_erase 191 | mc.EraseFlashBock(block_to_erase, 1) 192 | block_to_erase = block_to_erase + 1 193 | else: 194 | #state = states['IDLE'] 195 | state = states['DOWNLOAD_APP'] 196 | elif state == states['DOWNLOAD_APP']: 197 | mc.DownloadS19(r'C:\p\hgprojects\VWAppBuild\app\bin\AurixApp.s19') 198 | # Program 256 bytes(mininum possible) 199 | #mc.TransferSomeData(flash_sec_addr[8], range(255) + [ int(random.random()*255)]) 200 | state = states['IDLE'] 201 | 202 | 203 | 204 | 205 | #while (mc.state <> mc.states['IDLE'] and (uds.timedout == False)): 206 | # pass 207 | 208 | 209 | #for i in range(2): 210 | # if mc.state == mc.states['IDLE']: 211 | # break 212 | # else: 213 | # mc.Task() 214 | 215 | #try: 216 | # while (mc.state <> mc.states['IDLE'] and (uds.timedout == False)): 217 | # pass 218 | # if mc.state == mc.states['IDLE']: 219 | # print 'Operation sucessfully completed.' 220 | # if uds.timedout == True: 221 | # print "UDS timedout." 222 | 223 | #finally: 224 | # canif.rx_thread_active = False 225 | 226 | start_time = System.DateTime.Now 227 | 228 | try: 229 | state = states['DOWNLOAD_SBL'] 230 | #state = states['ERASE_APP'] 231 | while (state <> states['IDLE']) or (mc.state <> mc.states['IDLE']): 232 | main_func() 233 | 234 | finally: 235 | canif.rx_thread_active = False 236 | 237 | print "Time taken: ", (System.DateTime.Now-start_time).Seconds, " Seconds" 238 | 239 | #raw_input('Press any key to continue ...') 240 | -------------------------------------------------------------------------------- /ip_uds_bl/ip_uds_bl.pyproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | 2.0 6 | {3bd7605f-68ef-4246-a07d-3e13ba88d8af} 7 | . 8 | ip_uds_bl.py 9 | 10 | 11 | . 12 | 80659ab7-4d53-4e0c-8588-a766116cbd46 13 | IronPython (.NET) launcher 14 | 2.7 15 | . 16 | ip_uds_bl 17 | ip_uds_bl 18 | 19 | 20 | true 21 | false 22 | 23 | 24 | true 25 | false 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ip_uds_bl/myutils.py: -------------------------------------------------------------------------------- 1 | # 0x0001 program Trace (function decorator ???) 2 | # 0x0002 can_tp.xmit() 3 | # 0x8000 Stop on first transfer 4 | # 0x4000 CAN Messages 5 | # 0x2000 UDS Timeout Disable 6 | # 0x1000 debug info 7 | 8 | program_trace = 0x0001 9 | can_msg_trace = 0x4000 10 | debug_info = 0x1000 11 | debug_switch = 0 12 | 13 | def debug_print(mask, msg): 14 | if debug_switch & mask != 0: 15 | print msg 16 | 17 | def long_to_list(longdata): 18 | data = [(longdata >> 24) & 0xFF] 19 | data += [(longdata >> 16) & 0xFF] 20 | data += [(longdata >> 8) & 0xFF] 21 | data += [(longdata >> 0) & 0xFF] 22 | return(data) 23 | -------------------------------------------------------------------------------- /ip_uds_bl/uds.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import myutils 3 | 4 | class UDS(): 5 | """Unified Diagnostic Services""" 6 | def __init__(self, cantp): 7 | self.cantp = cantp 8 | self.can_tx_rdy = True 9 | self.active = False 10 | self.addressAndLengthFormatIdentifier = 0 11 | self.dataFormatIdentifier = 0 12 | cantp.event_sink = self.on_rcv_data 13 | self.routines = { 'ERASE_MEMORY' : 0xFF00, 'CHECK_ROUTINE' : 0x0202 } 14 | self.control_type = { 'START':1, 'STOP':2, 'GET_RESULTS': 3 } 15 | self.timedout = False 16 | self.rcv_timer = None 17 | 18 | def xmit(self, data): 19 | self.timedout = False 20 | self.cantp.xmit(data) 21 | #self.rcv_timer = threading.Timer(5, self.on_rcv_tout) # 5 seconds 22 | #self.rcv_timer.start() 23 | 24 | def on_rcv_tout(self): 25 | self.rcv_timer.cancel() 26 | self.rcv_timer = None 27 | self.timedout = True 28 | 29 | def on_rcv_data(self): 30 | myutils.debug_print(myutils.program_trace, 'UDS::on_rcv_data') 31 | if self.rcv_timer <> None: 32 | self.rcv_timer.cancel() 33 | self.rcv_timer = None 34 | self.event_sink() 35 | #if self.cantp.data_in[0] == (self.cantp.data_out[0]+0x40): 36 | # self.event_sink() 37 | #else: 38 | # print 'UDS response failed' 39 | # sys.exit(1) 40 | 41 | def TransferData(self, data): 42 | """ Transfers at the most 4095 bytes of data """ 43 | myutils.debug_print(myutils.program_trace, "UDS::TransferData") 44 | self.blockSequenceCounter = (self.blockSequenceCounter + 1) % 255 45 | self.cantp.Init() 46 | uds_data = [0x36, self.blockSequenceCounter] 47 | uds_data.extend(data) 48 | self.xmit(uds_data) 49 | 50 | 51 | def RequestDownload(self, address, data_size_bytes): 52 | myutils.debug_print(myutils.program_trace, "UDS::RequestDownload") 53 | self.cantp.Init() 54 | self.blockSequenceCounter = 0 55 | uds_data = [0x34] 56 | uds_data.extend([self.dataFormatIdentifier, self.addressAndLengthFormatIdentifier]) 57 | uds_data.extend(myutils.long_to_list(address)) 58 | uds_data.extend(myutils.long_to_list(data_size_bytes)) 59 | self.xmit(uds_data) 60 | 61 | def RequestTransferExit(self): 62 | myutils.debug_print(myutils.program_trace, "UDS::RequestTransferExit") 63 | self.cantp.Init() 64 | self.xmit([0x37]) 65 | 66 | def RoutineControl(self, routine_control_type, routine_id, op): 67 | myutils.debug_print(myutils.program_trace, "UDS::RoutineControl") 68 | self.cantp.Init() 69 | uds_data = [0x31] 70 | uds_data.append(routine_control_type) 71 | uds_data.append((routine_id >> 8) & 0xFF) 72 | uds_data.append(routine_id & 0xFF) 73 | uds_data.extend(op) 74 | self.xmit(uds_data) 75 | 76 | -------------------------------------------------------------------------------- /ip_uds_bl/vxlapi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satish77/ip_uds_bl_tool/1a221301a35e0ec8a099bf92e4e2affb92aae91b/ip_uds_bl/vxlapi.dll -------------------------------------------------------------------------------- /ip_uds_bl/vxlapi64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satish77/ip_uds_bl_tool/1a221301a35e0ec8a099bf92e4e2affb92aae91b/ip_uds_bl/vxlapi64.dll -------------------------------------------------------------------------------- /ip_uds_bl/vxlapi_NET20.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satish77/ip_uds_bl_tool/1a221301a35e0ec8a099bf92e4e2affb92aae91b/ip_uds_bl/vxlapi_NET20.dll --------------------------------------------------------------------------------