274 self.debug_break = False |
274 self.debug_break = False |
275 self.previous_plcstate = None |
275 self.previous_plcstate = None |
276 # copy StatusMethods so that it can be later customized |
276 # copy StatusMethods so that it can be later customized |
277 self.StatusMethods = [dic.copy() for dic in self.StatusMethods] |
277 self.StatusMethods = [dic.copy() for dic in self.StatusMethods] |
278 self.DebugToken = None |
278 self.DebugToken = None |
|
279 self.LastComplainDebugToken = None |
279 self.debug_status = PlcStatus.Stopped |
280 self.debug_status = PlcStatus.Stopped |
280 |
281 |
281 self.IECcodeDigest = None |
282 self.IECcodeDigest = None |
282 self.LastBuiltIECcodeDigest = None |
283 self.LastBuiltIECcodeDigest = None |
283 |
284 |
795 # Compute offset before ST resulting of transformation from user POUs |
796 # Compute offset before ST resulting of transformation from user POUs |
796 self.ProgramOffset = IECCodeContent.count("\n") |
797 self.ProgramOffset = IECCodeContent.count("\n") |
797 |
798 |
798 IECCodeContent += open(self._getIECgeneratedcodepath(), "r").read() |
799 IECCodeContent += open(self._getIECgeneratedcodepath(), "r").read() |
799 |
800 |
800 with open(self._getIECcodepath(), "w") as plc_file: |
801 IECcodepath = self._getIECcodepath() |
|
802 |
|
803 if not os.path.exists(IECcodepath): |
|
804 self.LastBuiltIECcodeDigest = None |
|
805 |
|
806 with open(IECcodepath, "w") as plc_file: |
801 plc_file.write(IECCodeContent) |
807 plc_file.write(IECCodeContent) |
802 |
808 |
803 hasher = hashlib.md5() |
809 hasher = hashlib.md5() |
804 hasher.update(IECCodeContent) |
810 hasher.update(IECCodeContent) |
805 self.IECcodeDigest = hasher.hexdigest() |
811 self.IECcodeDigest = hasher.hexdigest() |
964 try: |
970 try: |
965 csvfile = os.path.join(self._getBuildPath(), "VARIABLES.csv") |
971 csvfile = os.path.join(self._getBuildPath(), "VARIABLES.csv") |
966 # describes CSV columns |
972 # describes CSV columns |
967 ProgramsListAttributeName = ["num", "C_path", "type"] |
973 ProgramsListAttributeName = ["num", "C_path", "type"] |
968 VariablesListAttributeName = [ |
974 VariablesListAttributeName = [ |
969 "num", "vartype", "IEC_path", "C_path", "type", "derived"] |
975 "num", "vartype", "IEC_path", "C_path", "type", "derived", "retain"] |
970 self._ProgramList = [] |
976 self._ProgramList = [] |
971 self._VariablesList = [] |
977 self._VariablesList = [] |
972 self._DbgVariablesList = [] |
978 self._DbgVariablesList = [] |
973 self._IECPathToIdx = {} |
979 self._IECPathToIdx = {} |
974 |
980 |
1045 """ |
1051 """ |
1046 self.GetIECProgramsAndVariables() |
1052 self.GetIECProgramsAndVariables() |
1047 |
1053 |
1048 # prepare debug code |
1054 # prepare debug code |
1049 variable_decl_array = [] |
1055 variable_decl_array = [] |
1050 bofs = 0 |
1056 retain_indexes = [] |
1051 for v in self._DbgVariablesList: |
1057 for i, v in enumerate(self._DbgVariablesList): |
1052 sz = DebugTypesSize.get(v["type"], 0) |
1058 variable_decl_array.append( |
1053 variable_decl_array += [ |
|
1054 "{&(%(C_path)s), " % v + |
1059 "{&(%(C_path)s), " % v + |
1055 { |
1060 { |
1056 "EXT": "%(type)s_P_ENUM", |
1061 "EXT": "%(type)s_P_ENUM", |
1057 "IN": "%(type)s_P_ENUM", |
1062 "IN": "%(type)s_P_ENUM", |
1058 "MEM": "%(type)s_O_ENUM", |
1063 "MEM": "%(type)s_O_ENUM", |
1059 "OUT": "%(type)s_O_ENUM", |
1064 "OUT": "%(type)s_O_ENUM", |
1060 "VAR": "%(type)s_ENUM" |
1065 "VAR": "%(type)s_ENUM" |
1061 }[v["vartype"]] % v + |
1066 }[v["vartype"]] % v + |
1062 "}"] |
1067 "}") |
1063 bofs += sz |
1068 |
|
1069 if v["retain"] == "1": |
|
1070 retain_indexes.append("/* "+v["C_path"]+" */ "+str(i)) |
|
1071 |
1064 debug_code = targets.GetCode("plc_debug.c") % { |
1072 debug_code = targets.GetCode("plc_debug.c") % { |
1065 "buffer_size": bofs, |
|
1066 "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" % |
1073 "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" % |
1067 p for p in self._ProgramList]), |
1074 p for p in self._ProgramList]), |
1068 "extern_variables_declarations": "\n".join([ |
1075 "extern_variables_declarations": "\n".join([ |
1069 { |
1076 { |
1070 "EXT": "extern __IEC_%(type)s_p %(C_path)s;", |
1077 "EXT": "extern __IEC_%(type)s_p %(C_path)s;", |
1074 "VAR": "extern __IEC_%(type)s_t %(C_path)s;", |
1081 "VAR": "extern __IEC_%(type)s_t %(C_path)s;", |
1075 "FB": "extern %(type)s %(C_path)s;" |
1082 "FB": "extern %(type)s %(C_path)s;" |
1076 }[v["vartype"]] % v |
1083 }[v["vartype"]] % v |
1077 for v in self._VariablesList if v["C_path"].find('.') < 0]), |
1084 for v in self._VariablesList if v["C_path"].find('.') < 0]), |
1078 "variable_decl_array": ",\n".join(variable_decl_array), |
1085 "variable_decl_array": ",\n".join(variable_decl_array), |
|
1086 "retain_vardsc_index_array": ",\n".join(retain_indexes), |
1079 "var_access_code": targets.GetCode("var_access.c") |
1087 "var_access_code": targets.GetCode("var_access.c") |
1080 } |
1088 } |
1081 |
1089 |
1082 return debug_code |
1090 return debug_code |
1083 |
1091 |
1548 if not IECdebug_data[4] and len(values_buffer) > 0: |
1556 if not IECdebug_data[4] and len(values_buffer) > 0: |
1549 values_buffer[-1] = (value, forced) |
1557 values_buffer[-1] = (value, forced) |
1550 else: |
1558 else: |
1551 values_buffer.append((value, forced)) |
1559 values_buffer.append((value, forced)) |
1552 self.DebugTicks.append(debug_tick) |
1560 self.DebugTicks.append(debug_tick) |
|
1561 else: |
|
1562 # complain if trace is incomplete, but only once per debug session |
|
1563 if self.LastComplainDebugToken != self.DebugToken : |
|
1564 self.logger.write_warning( |
|
1565 _("Debug: target couldn't trace all requested variables.\n")) |
|
1566 self.LastComplainDebugToken = self.DebugToken |
|
1567 |
|
1568 |
1553 |
1569 |
1554 buffers, self.DebugValuesBuffers = (self.DebugValuesBuffers, |
1570 buffers, self.DebugValuesBuffers = (self.DebugValuesBuffers, |
1555 [list() for dummy in xrange(len(self.TracedIECPath))]) |
1571 [list() for dummy in xrange(len(self.TracedIECPath))]) |
1556 |
1572 |
1557 ticks, self.DebugTicks = self.DebugTicks, [] |
1573 ticks, self.DebugTicks = self.DebugTicks, [] |
1558 |
1574 |
1559 return debug_status, ticks, buffers |
1575 return debug_status, ticks, buffers |
|
1576 |
|
1577 RegisterDebugVariableErrorCodes = { |
|
1578 # TRACE_LIST_OVERFLOW |
|
1579 1 : _("Debug: Too many variables traced. Max 1024.\n"), |
|
1580 # FORCE_LIST_OVERFLOW |
|
1581 2 : _("Debug: Too many variables forced. Max 256.\n"), |
|
1582 # FORCE_BUFFER_OVERFLOW |
|
1583 3 : _("Debug: Cumulated forced variables size too large. Max 1KB.\n") |
|
1584 } |
1560 |
1585 |
1561 def RegisterDebugVarToConnector(self): |
1586 def RegisterDebugVarToConnector(self): |
1562 Idxs = [] |
1587 Idxs = [] |
1563 self.TracedIECPath = [] |
1588 self.TracedIECPath = [] |
1564 self.TracedIECTypes = [] |
1589 self.TracedIECTypes = [] |
1589 if Idxs: |
1614 if Idxs: |
1590 Idxs.sort() |
1615 Idxs.sort() |
1591 IdxsT = zip(*Idxs) |
1616 IdxsT = zip(*Idxs) |
1592 self.TracedIECPath = IdxsT[3] |
1617 self.TracedIECPath = IdxsT[3] |
1593 self.TracedIECTypes = IdxsT[1] |
1618 self.TracedIECTypes = IdxsT[1] |
1594 self.DebugToken = self._connector.SetTraceVariablesList(zip(*IdxsT[0:3])) |
1619 res = self._connector.SetTraceVariablesList(zip(*IdxsT[0:3])) |
|
1620 if res is not None and res > 0: |
|
1621 self.DebugToken = res |
|
1622 else: |
|
1623 self.DebugToken = None |
|
1624 self.logger.write_warning( |
|
1625 self.RegisterDebugVariableErrorCodes.get( |
|
1626 -res, _("Debug: Unknown error"))) |
1595 else: |
1627 else: |
1596 self.TracedIECPath = [] |
1628 self.TracedIECPath = [] |
1597 self._connector.SetTraceVariablesList([]) |
1629 self._connector.SetTraceVariablesList([]) |
1598 self.DebugToken = None |
1630 self.DebugToken = None |
1599 self.debug_status, _debug_ticks, _buffers = self.SnapshotAndResetDebugValuesBuffers() |
1631 self.debug_status, _debug_ticks, _buffers = self.SnapshotAndResetDebugValuesBuffers() |