Compare commits
29 Commits
Author | SHA1 | Date |
---|---|---|
Dongly | 775ca9f499 | |
Dongly | 0af2878317 | |
Dongly | ea8c32594c | |
chinky | aa64af85fd | |
Hans-Erik Floryd | 83c6264f99 | |
Windsgo | d478bce787 | |
Chinky | 1bdff2341d | |
Chinky | 750fc89ebb | |
chinky | 9ced549488 | |
Chinky | 4ef663c66d | |
Chinky | 22420644c2 | |
Chinky | d29d9d4dac | |
Chinky | 1ab222fbd1 | |
Chinky | 8ec3391cbd | |
Chinky | 9c8dd8c2a1 | |
Chinky | 35bfaf70c3 | |
Chinky | a279640e26 | |
Chinky | 5d2b04e7b3 | |
Chinky | 5fbafd07ec | |
Chinky | 25fd9f81fb | |
Chinky | be172749b2 | |
Chinky | aa2c438d21 | |
Chinky | 2fabd78466 | |
Chinky | 1970f178fd | |
Chinky | 8479266ba2 | |
Chinky | d18d90cce5 | |
Chinky | 0a4cdc48ce | |
Chinky | 636c2b63bc | |
Chinky | deeb945dae |
|
@ -4,3 +4,5 @@ install
|
|||
/doc/latex
|
||||
/doc/html
|
||||
tags
|
||||
*.pyc
|
||||
test/linux/eceeprom/sn.csv
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/soem/**",
|
||||
"${workspaceFolder}/oshw/linux/**",
|
||||
"${workspaceFolder}/oshw/linux/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/gcc-12",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++14",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.cmake-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"time.h": "c",
|
||||
"time_t.h": "c",
|
||||
"struct_timeval.h": "c",
|
||||
"features.h": "c",
|
||||
"random": "c",
|
||||
"logn.h": "c",
|
||||
"timesize.h": "c"
|
||||
},
|
||||
"cmake.configureOnOpen": true
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cppbuild",
|
||||
"label": "C/C++: gcc-13 生成活动文件",
|
||||
"command": "/usr/bin/gcc-13",
|
||||
"args": [
|
||||
"-fdiagnostics-color=always",
|
||||
"-g",
|
||||
"${file}",
|
||||
"-o",
|
||||
"${fileDirname}/${fileBasenameNoExtension}"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${fileDirname}"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"detail": "调试器生成的任务。"
|
||||
}
|
||||
],
|
||||
"version": "2.0.0"
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules")
|
||||
# SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
|
||||
|
||||
project(SOEM
|
||||
DESCRIPTION "Simple Open EtherCAT Master"
|
||||
VERSION 1.4.0
|
||||
|
@ -33,7 +35,7 @@ if(WIN32)
|
|||
set(OS_LIBS wpcap.lib Packet.lib Ws2_32.lib Winmm.lib)
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
set(OS "linux")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -fPIC")
|
||||
set(OS_LIBS pthread rt)
|
||||
elseif(APPLE)
|
||||
# This must come *before* linux or MacOSX will identify as Unix.
|
||||
|
@ -106,8 +108,10 @@ install(FILES
|
|||
DESTINATION ${SOEM_INCLUDE_INSTALL_DIR})
|
||||
|
||||
if(BUILD_TESTS)
|
||||
add_subdirectory(test/simple_ng)
|
||||
add_subdirectory(test/linux/slaveinfo)
|
||||
add_subdirectory(test/linux/eepromtool)
|
||||
add_subdirectory(test/linux/simple_test)
|
||||
# add_subdirectory(test/simple_ng)
|
||||
add_subdirectory(test/linux/ecslaveinfo)
|
||||
add_subdirectory(test/linux/eceeprom)
|
||||
# add_subdirectory(test/linux/simple_test)
|
||||
add_subdirectory(test/linux/tj30_test)
|
||||
# add_subdirectory(test/linux/red_test)
|
||||
endif()
|
||||
|
|
|
@ -54,7 +54,7 @@ boolean osal_timer_is_expired (osal_timert * self)
|
|||
stop_time.tv_usec = self->stop_time.usec;
|
||||
is_not_yet_expired = timercmp (¤t_time, &stop_time, <);
|
||||
|
||||
return is_not_yet_expired == FALSE;
|
||||
return is_not_yet_expired == FALSE; // !is_not_yet_expired
|
||||
}
|
||||
|
||||
int osal_usleep(uint32 usec)
|
||||
|
|
|
@ -87,6 +87,10 @@ int ecx_FOEread(ecx_contextt *context, uint16 slave, char *filename, uint32 pass
|
|||
aFOEp = (ec_FOEt *)&MbxIn;
|
||||
FOEp = (ec_FOEt *)&MbxOut;
|
||||
fnsize = (uint16)strlen(filename);
|
||||
if (fnsize > EC_MAXFOEDATA)
|
||||
{
|
||||
fnsize = EC_MAXFOEDATA;
|
||||
}
|
||||
maxdata = context->slavelist[slave].mbx_l - 12;
|
||||
if (fnsize > maxdata)
|
||||
{
|
||||
|
@ -216,6 +220,10 @@ int ecx_FOEwrite(ecx_contextt *context, uint16 slave, char *filename, uint32 pas
|
|||
FOEp = (ec_FOEt *)&MbxOut;
|
||||
dofinalzero = TRUE;
|
||||
fnsize = (uint16)strlen(filename);
|
||||
if (fnsize > EC_MAXFOEDATA)
|
||||
{
|
||||
fnsize = EC_MAXFOEDATA;
|
||||
}
|
||||
maxdata = context->slavelist[slave].mbx_l - 12;
|
||||
if (fnsize > maxdata)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
|
||||
ColumnLimit: 100
|
||||
AccessModifierOffset: -4
|
||||
# 连续赋值时,对齐所有等号
|
||||
AlignConsecutiveAssignments: false
|
||||
# 连续宏时,对齐所有宏
|
||||
AlignConsecutiveMacros: true
|
||||
# 连续声明时,对齐所有声明的变量名
|
||||
AlignConsecutiveDeclarations: true
|
||||
# 水平对齐二元和三元表达式的操作数
|
||||
AlignOperands: true
|
||||
# 对齐连续的尾随的注释
|
||||
AlignTrailingComments:true
|
||||
# 允许函数声明的所有参数在放在下一行
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
# 允许短的块放在同一行
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
BreakBeforeBraces: Allman
|
||||
BraceWrapping:
|
||||
AfterFunction: true
|
||||
BreakBeforeBinaryOperators: true
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
NamespaceIndentation: All
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
# 代码块的开始处不能有空行
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
# 连续的空行只保留至多两个,这样的话,1个和2个会有区别感
|
||||
MaxEmptyLinesToKeep: 2
|
||||
|
||||
...
|
||||
|
|
@ -250,7 +250,7 @@ void add_timespec(struct timespec *ts, int64 addtime)
|
|||
sec = (addtime - nsec) / NSEC_PER_SEC;
|
||||
ts->tv_sec += sec;
|
||||
ts->tv_nsec += nsec;
|
||||
if ( ts->tv_nsec > NSEC_PER_SEC )
|
||||
if ( ts->tv_nsec >= NSEC_PER_SEC )
|
||||
{
|
||||
nsec = ts->tv_nsec % NSEC_PER_SEC;
|
||||
ts->tv_sec += (ts->tv_nsec - nsec) / NSEC_PER_SEC;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
*.csv
|
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
|
||||
<!-- AX58100 EVB ESI Sample File - "AX58100 EVB (Digital 16-Input/16-Output)" -->
|
||||
<EtherCATInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="EtherCATInfo.xsd" Version="1.2">
|
||||
<Vendor>
|
||||
<Id>#x00000b95</Id>
|
||||
<Name>ASIX Electronics Corporation</Name>
|
||||
<ImageData16x14>424DE6000000000000007600000028000000100000000E000000010004000000000070000000120B0000120B0000100000001000000000000000000080000080000000808000800000008000800080800000C0C0C000808080000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00FFF4444444444FFFFF448888888844FFF484448FF844484F4888444FF44488844F8F44444444F8F448884444444488844F8F84444448F8F448888444444888844F8F8F4444F8F8F4F48888444488884FFF4F8F4444F8F4FFFF448884488844FFFFFF4F8448F4FFFFFFFFF444444FFFFF</ImageData16x14>
|
||||
</Vendor>
|
||||
<Descriptions>
|
||||
<Groups>
|
||||
<Group>
|
||||
<Type>AX58100_EVB</Type>
|
||||
<Name LcId="1031">AX58100_EVB</Name>
|
||||
<ImageData16x14>424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000120B0000120B00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FF0000FF0000FF0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FF0000FF0000FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FF0000FFFF00FF008000008000008000008000008000008000008000008000404040404040404040404040404040404040404040404040008000007FFF007FFF00800000800000800000800000800040404000800000800000800000800000800000800040404000800000800000800000800000800000800000800000800040404000800000800000800000800000800000800040404000800000800000800000800000800000800000800000800040404000800000800000800000800000800000800040404000800000800000800000800000800000800000800000800040404040404040404040404040404040404040404040404000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000FFFF00800000FFFF00800000800000FFFF00800000FFFF00800000800000800000FFFF00800000FFFF00800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000FFFF00800000FFFF00800000800000FFFF00800000FFFF00800000800000800000FFFF00800000FFFF008000008000008000008000008000008000008000008000008000008000008000008000008000008000008000008000008000</ImageData16x14>
|
||||
</Group>
|
||||
</Groups>
|
||||
|
||||
<Devices>
|
||||
<!-- DIO, GPIO, FMMU=2, SM=3, DI=16, DO=16, ProductCode="#x00010200" RevisionNo="#x00000001" -->
|
||||
<Device Physics="YY">
|
||||
<Type ProductCode="#x00010200" RevisionNo="#x00000001">AX58100_EVB_DIO_16</Type>
|
||||
<Name LcId="1031">AX58100 EVB (Digital 16-Input/16-Output)</Name>
|
||||
<GroupType>AX58100_EVB</GroupType>
|
||||
<Fmmu>Outputs</Fmmu>
|
||||
<Fmmu>Inputs</Fmmu>
|
||||
<Sm StartAddress="#x0f02" ControlByte="#x44" Enable="1" OpOnly="1">Outputs</Sm>
|
||||
<Sm StartAddress="#x0f03" ControlByte="#x44" Enable="1" OpOnly="1">Outputs</Sm>
|
||||
<Sm StartAddress="#x1000" ControlByte="0" Enable="1">Inputs</Sm>
|
||||
<RxPdo Fixed="1" Sm="0">
|
||||
<Index>#x1a00</Index>
|
||||
<Name>Byte 0</Name>
|
||||
<Entry>
|
||||
<Index>#x3101</Index>
|
||||
<SubIndex>1</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Output</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</RxPdo>
|
||||
<RxPdo Fixed="1" Sm="1">
|
||||
<Index>#x1a01</Index>
|
||||
<Name>Byte 1</Name>
|
||||
<Entry>
|
||||
<Index>#x3101</Index>
|
||||
<SubIndex>2</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Output</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</RxPdo>
|
||||
<TxPdo Fixed="1" Sm="2">
|
||||
<Index>#x1600</Index>
|
||||
<Name>Byte 0</Name>
|
||||
<Entry>
|
||||
<Index>#x3001</Index>
|
||||
<SubIndex>1</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Input</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</TxPdo>
|
||||
<TxPdo Fixed="1" Sm="2">
|
||||
<Index>#x1601</Index>
|
||||
<Name>Byte 1</Name>
|
||||
<Entry>
|
||||
<Index>#x3001</Index>
|
||||
<SubIndex>2</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Input</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</TxPdo>
|
||||
<Dc>
|
||||
<OpMode>
|
||||
<Name>DcOff</Name>
|
||||
<Desc>DC unused</Desc>
|
||||
<AssignActivate>#x0000</AssignActivate>
|
||||
</OpMode>
|
||||
<OpMode>
|
||||
<Name>DcSync</Name>
|
||||
<Desc>DC for synchronization</Desc>
|
||||
<AssignActivate>#x0100</AssignActivate>
|
||||
<CycleTimeSync0 Factor="1">0</CycleTimeSync0>
|
||||
<ShiftTimeSync0>0</ShiftTimeSync0>
|
||||
</OpMode>
|
||||
</Dc>
|
||||
<Eeprom>
|
||||
<ByteSize>2048</ByteSize>
|
||||
<ConfigData>040d0044102700ff000000000000</ConfigData>
|
||||
</Eeprom>
|
||||
</Device>
|
||||
|
||||
</Devices>
|
||||
</Descriptions>
|
||||
</EtherCATInfo>
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
file(GLOB SOURCES *.c)
|
||||
add_executable(eceeprom ${SOURCES})
|
||||
target_link_libraries(eceeprom soem)
|
||||
install(TARGETS eceeprom DESTINATION bin)
|
||||
|
||||
set(LIB_SRC eceeprom.c)
|
||||
add_library(eceeprom_lib SHARED ${LIB_SRC})
|
||||
set_target_properties(eceeprom_lib PROPERTIES OUTPUT_NAME "eceeprom")
|
||||
target_link_libraries(eceeprom_lib soem)
|
||||
|
||||
add_library(eceeprom_static STATIC ${LIB_SRC})
|
||||
set_target_properties(eceeprom_static PROPERTIES OUTPUT_NAME "eceeprom")
|
||||
target_link_libraries(eceeprom_static soem)
|
||||
|
||||
target_include_directories(eceeprom_static
|
||||
PUBLIC .)
|
||||
|
||||
install(TARGETS eceeprom_lib LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
|
||||
install(FILES eceeprom.h DESTINATION include)
|
||||
|
||||
install(FILES ec_eeprom.py ec_eeprom301616.py ch_eeprom.py sn.py test.sh ch.sh DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(FILES database.py Verhoeff.py config.toml TJ30-1616DN-EEPROM.bin TongJi_TJ03-1616DN.xml DESTINATION bin)
|
Binary file not shown.
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
|
||||
<!-- TJ30-1616DN ESI File - "TJ30-1616DN (Digital 16-Input/16-Output)" -->
|
||||
<EtherCATInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="EtherCATInfo.xsd" Version="1.2">
|
||||
<Vendor>
|
||||
<Id>#x00000b95</Id>
|
||||
<Name>ASIX Electronics Corporation</Name>
|
||||
<ImageData16x14>424DE6000000000000007600000028000000100000000E000000010004000000000070000000120B0000120B0000100000001000000000000000000080000080000000808000800000008000800080800000C0C0C000808080000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00FFF4444444444FFFFF448888888844FFF484448FF844484F4888444FF44488844F8F44444444F8F448884444444488844F8F84444448F8F448888444444888844F8F8F4444F8F8F4F48888444488884FFF4F8F4444F8F4FFFF448884488844FFFFFF4F8448F4FFFFFFFFF444444FFFFF</ImageData16x14>
|
||||
</Vendor>
|
||||
<Descriptions>
|
||||
<Groups>
|
||||
<Group>
|
||||
<Type>TJ30-1616DN</Type>
|
||||
<Name LcId="1031">TJ30-1616DN</Name>
|
||||
<ImageData16x14>424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000120B0000120B00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FF0000FF0000FF0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FF0000FF0000FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0000FFFF00FFFF00FFFF00FF0000FFFF00FF008000008000008000008000008000008000008000008000404040404040404040404040404040404040404040404040008000007FFF007FFF00800000800000800000800000800040404000800000800000800000800000800000800040404000800000800000800000800000800000800000800000800040404000800000800000800000800000800000800040404000800000800000800000800000800000800000800000800040404000800000800000800000800000800000800040404000800000800000800000800000800000800000800000800040404040404040404040404040404040404040404040404000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000FFFF00800000FFFF00800000800000FFFF00800000FFFF00800000800000800000FFFF00800000FFFF00800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000800000FFFF00800000FFFF00800000800000FFFF00800000FFFF00800000800000800000FFFF00800000FFFF008000008000008000008000008000008000008000008000008000008000008000008000008000008000008000008000008000</ImageData16x14>
|
||||
</Group>
|
||||
</Groups>
|
||||
|
||||
<Devices>
|
||||
<!-- DIO, GPIO, FMMU=2, SM=3, DI=16, DO=16, ProductCode="#x00010200" RevisionNo="#x00000001" -->
|
||||
<Device Physics="YY">
|
||||
<Type ProductCode="#x00010200" RevisionNo="#x00000001">TJ30-1616DN</Type>
|
||||
<Name LcId="1031">TJ30-1616DN (Digital 16-Input/16-Output)</Name>
|
||||
<GroupType>TJ30-1616DN</GroupType>
|
||||
<Fmmu>Outputs</Fmmu>
|
||||
<Fmmu>Inputs</Fmmu>
|
||||
<Sm StartAddress="#x0f02" ControlByte="#x44" Enable="1" OpOnly="1">Outputs</Sm>
|
||||
<Sm StartAddress="#x0f03" ControlByte="#x44" Enable="1" OpOnly="1">Outputs</Sm>
|
||||
<Sm StartAddress="#x1000" ControlByte="0" Enable="1">Inputs</Sm>
|
||||
<RxPdo Fixed="1" Sm="0">
|
||||
<Index>#x1a00</Index>
|
||||
<Name>Byte 0</Name>
|
||||
<Entry>
|
||||
<Index>#x3101</Index>
|
||||
<SubIndex>1</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Output</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</RxPdo>
|
||||
<RxPdo Fixed="1" Sm="1">
|
||||
<Index>#x1a01</Index>
|
||||
<Name>Byte 1</Name>
|
||||
<Entry>
|
||||
<Index>#x3101</Index>
|
||||
<SubIndex>2</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Output</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</RxPdo>
|
||||
<TxPdo Fixed="1" Sm="2">
|
||||
<Index>#x1600</Index>
|
||||
<Name>Byte 0</Name>
|
||||
<Entry>
|
||||
<Index>#x3001</Index>
|
||||
<SubIndex>1</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Input</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</TxPdo>
|
||||
<TxPdo Fixed="1" Sm="2">
|
||||
<Index>#x1601</Index>
|
||||
<Name>Byte 1</Name>
|
||||
<Entry>
|
||||
<Index>#x3001</Index>
|
||||
<SubIndex>2</SubIndex>
|
||||
<BitLen>8</BitLen>
|
||||
<Name>Input</Name>
|
||||
<DataType>BITARR8</DataType>
|
||||
</Entry>
|
||||
</TxPdo>
|
||||
<Dc>
|
||||
<OpMode>
|
||||
<Name>DcOff</Name>
|
||||
<Desc>DC unused</Desc>
|
||||
<AssignActivate>#x0000</AssignActivate>
|
||||
</OpMode>
|
||||
<OpMode>
|
||||
<Name>DcSync</Name>
|
||||
<Desc>DC for synchronization</Desc>
|
||||
<AssignActivate>#x0100</AssignActivate>
|
||||
<CycleTimeSync0 Factor="1">0</CycleTimeSync0>
|
||||
<ShiftTimeSync0>0</ShiftTimeSync0>
|
||||
</OpMode>
|
||||
</Dc>
|
||||
<Eeprom>
|
||||
<ByteSize>2048</ByteSize>
|
||||
<ConfigData>040d0044102700ff000000000000</ConfigData>
|
||||
</Eeprom>
|
||||
</Device>
|
||||
|
||||
</Devices>
|
||||
</Descriptions>
|
||||
</EtherCATInfo>
|
|
@ -0,0 +1,53 @@
|
|||
#!`which python`
|
||||
|
||||
# Copyright (c) 2012, Simon David Pratt <me@simondavidpratt.com>
|
||||
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
d_table = [[0,1,2,3,4,5,6,7,8,9],
|
||||
[1,2,3,4,0,6,7,8,9,5],
|
||||
[2,3,4,0,1,7,8,9,5,6],
|
||||
[3,4,0,1,2,8,9,5,6,7],
|
||||
[4,0,1,2,3,9,5,6,7,8],
|
||||
[5,9,8,7,6,0,4,3,2,1],
|
||||
[6,5,9,8,7,1,0,4,3,2],
|
||||
[7,6,5,9,8,2,1,0,4,3],
|
||||
[8,7,6,5,9,3,2,1,0,4],
|
||||
[9,8,7,6,5,4,3,2,1,0]]
|
||||
|
||||
def d(j,k):
|
||||
return d_table[j][k]
|
||||
|
||||
p_table = [[0,1,2,3,4,5,6,7,8,9],
|
||||
[1,5,7,6,2,8,3,0,9,4],
|
||||
[5,8,0,3,7,9,6,1,4,2],
|
||||
[8,9,1,6,0,4,3,5,2,7],
|
||||
[9,4,5,3,1,2,6,8,7,0],
|
||||
[4,2,8,6,5,7,3,9,0,1],
|
||||
[2,7,9,3,8,0,6,4,1,5],
|
||||
[7,0,4,6,9,1,3,2,5,8]]
|
||||
|
||||
def p(pos,num):
|
||||
return p_table[pos%8][num]
|
||||
|
||||
def checksum(digits_str):
|
||||
c=0
|
||||
l = len(digits_str)-1
|
||||
for i in range(0,l):
|
||||
c=d(c,p(i,int(digits_str[l-i])))
|
||||
return c
|
||||
|
||||
def verify(digits_str):
|
||||
return checksum(digits_str[:-1]) == int(digits_str[-1])
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/env bash
|
||||
|
||||
dir=$(cd "$(dirname $0)";pwd)
|
||||
${dir}/ch_eeprom.py
|
||||
|
||||
echo 请先断电,再通电
|
||||
read -n 1 -s -r -p "按任意键继续..."
|
||||
sleep 2
|
||||
# ${dir}/ecslaveinfo enp3s0f1
|
||||
${dir}/tj30_test enp3s0f0
|
|
@ -0,0 +1,65 @@
|
|||
#!/root/venv/bin/python
|
||||
|
||||
import sys
|
||||
from ctypes import *
|
||||
from database import *
|
||||
from sn import *
|
||||
|
||||
|
||||
ll = cdll.LoadLibrary
|
||||
# ece = ll("../../../build/test/linux/eceeprom/libeceeprom.so")
|
||||
ece = ll("../lib/libeceeprom.so")
|
||||
|
||||
|
||||
def change_multi_eeprom(count: int, eeprome_file: str):
|
||||
|
||||
# 当从机数量大于1时,不写最后一个
|
||||
if count == 1:
|
||||
count = 2
|
||||
for i in range(1, count):
|
||||
sn = ece.ecEepromGetSN(i)
|
||||
print(f"Get origin SN: {sn}")
|
||||
if sn==0:
|
||||
print("SN is ERROR!!")
|
||||
while True:
|
||||
pass
|
||||
|
||||
print(f"Write file '{eeprome_file}' to slave EEPROM #{i}, SN = {sn} \n")
|
||||
rc = ece.ecFileToEeprom(
|
||||
c_int(i), c_char_p(eeprome_file), c_bool(False), c_uint(sn)
|
||||
)
|
||||
if rc > 0:
|
||||
print("update eeprom sussus\n")
|
||||
else:
|
||||
print("Update EEPROM FAIL!\n")
|
||||
|
||||
|
||||
def main():
|
||||
is_force = False
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "-force":
|
||||
is_force = True
|
||||
|
||||
ifname = b"enp3s0f0"
|
||||
if ece.ec_init(c_char_p(ifname)) <= 0:
|
||||
print("No socket connection on %s\nExcecute as root\n" % ifname)
|
||||
return -1
|
||||
print("ec_init on %s succeeded.\n" % ifname)
|
||||
# Get the number of slaves
|
||||
slaveCount = ece.ecGetSlaveCount()
|
||||
if slaveCount < 1:
|
||||
print("No slaves found!\n")
|
||||
ece.ec_close()
|
||||
return -1
|
||||
print("Found %d slave(s)\n" % slaveCount)
|
||||
|
||||
# # # Write the SN
|
||||
# session = db_init()
|
||||
|
||||
eeprom_file = b"./AX58100_EVD_16DI_16DO.bin"
|
||||
|
||||
|
||||
change_multi_eeprom(slaveCount, eeprom_file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,6 @@
|
|||
[database]
|
||||
user = "root"
|
||||
password = "lldlcj123"
|
||||
host = "192.168.222.5"
|
||||
port = 6306
|
||||
database = "product"
|
|
@ -0,0 +1,141 @@
|
|||
#!/bin/env python
|
||||
|
||||
from sqlalchemy import (
|
||||
create_engine,
|
||||
Column,
|
||||
Integer,
|
||||
String,
|
||||
DateTime,
|
||||
ForeignKey,
|
||||
func,
|
||||
UniqueConstraint,
|
||||
select,
|
||||
)
|
||||
from sqlalchemy.orm import sessionmaker, relationship, DeclarativeBase
|
||||
import toml
|
||||
|
||||
|
||||
# Declare models
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
|
||||
class Products(Base):
|
||||
__tablename__ = "products"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name = Column(String(128), nullable=False)
|
||||
prefix = Column(String(16))
|
||||
product_code = Column(String(32))
|
||||
note = Column(String(512))
|
||||
created_at = Column(DateTime, server_default=func.current_timestamp())
|
||||
updated_at = Column(
|
||||
DateTime,
|
||||
server_default=func.current_timestamp(),
|
||||
server_onupdate=func.current_timestamp(),
|
||||
)
|
||||
product_list = relationship("ProductList", back_populates="products")
|
||||
__table_args__ = (UniqueConstraint("name", "prefix", "product_code"),)
|
||||
|
||||
|
||||
class ProductList(Base):
|
||||
__tablename__ = "product_list"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
|
||||
sn = Column(Integer, nullable=False)
|
||||
note = Column(String(128))
|
||||
created_at = Column(DateTime, server_default=func.current_timestamp())
|
||||
products = relationship("Products", back_populates="product_list")
|
||||
__table_args__ = (UniqueConstraint("sn"),)
|
||||
|
||||
|
||||
# Database initialization
|
||||
def db_init():
|
||||
config = toml.load("config.toml")
|
||||
db_config = config["database"]
|
||||
|
||||
user = db_config["user"]
|
||||
password = db_config["password"]
|
||||
host = db_config["host"]
|
||||
port = db_config["port"]
|
||||
database = db_config["database"]
|
||||
|
||||
engine = create_engine(
|
||||
f"mysql+pymysql://{user}:{password}@{host}:{port}/{database}?charset=utf8mb4",
|
||||
# echo=True,
|
||||
)
|
||||
Base.metadata.create_all(engine)
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
return session
|
||||
|
||||
|
||||
# Get the last sn for a given product name
|
||||
def get_last_sn(session, product_name: str) -> int:
|
||||
stmt = (
|
||||
select(ProductList.sn)
|
||||
.join(ProductList.products)
|
||||
.order_by(ProductList.created_at.desc())
|
||||
.filter_by(name=product_name)
|
||||
)
|
||||
last_sn_record = session.execute(stmt).first()
|
||||
if last_sn_record is not None:
|
||||
last_sn = int(last_sn_record.sn)
|
||||
else:
|
||||
last_sn = 0
|
||||
return last_sn
|
||||
|
||||
|
||||
# check the new_sn valile for a given product name,if new_sn is exist, reture true
|
||||
def sn_is_exist(session, product_name: str, sn: int) -> bool:
|
||||
stmt = (
|
||||
select(func.count())
|
||||
.select_from(ProductList)
|
||||
.join(ProductList.products)
|
||||
.filter(Products.name == product_name, ProductList.sn == sn)
|
||||
)
|
||||
count = session.execute(stmt).scalar()
|
||||
return count != 0
|
||||
|
||||
|
||||
# Get the sn perfix for a given product name
|
||||
def get_product_info(session, product_name: str):
|
||||
stmt = select(Products.prefix, Products.product_code).filter_by(name=product_name)
|
||||
product = session.execute(stmt).first()
|
||||
prefix = ""
|
||||
product_code = ""
|
||||
if product is not None:
|
||||
if product.prefix is not None:
|
||||
prefix = product.prefix
|
||||
if product.product_code is not None:
|
||||
product_code = product.product_code
|
||||
return product_code, prefix
|
||||
|
||||
|
||||
# Set a new sn for a given product
|
||||
def save_new_sn_to_db(session, product_name, sn):
|
||||
product = session.query(Products).filter_by(name=product_name).first()
|
||||
if sn_is_exist(session, product_name, sn):
|
||||
print("Error: SN already exists.")
|
||||
return
|
||||
new_product_list = ProductList(product_id=product.id, sn=sn)
|
||||
session.add(new_product_list)
|
||||
session.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
session = db_init()
|
||||
product_name = "TJ30-1616DN"
|
||||
print("Get last sn ...")
|
||||
last_sn = get_last_sn(session, product_name)
|
||||
print("Last sn for product", product_name, "is:", last_sn)
|
||||
product_code, prefix = get_product_info(session, product_name)
|
||||
print(f"product_code = {product_code}, prefix = {prefix}")
|
||||
new_sn = last_sn
|
||||
print(f"new_sn = {new_sn}")
|
||||
sn_ok = sn_is_exist(session, product_name, new_sn)
|
||||
print(f"sn_ok = {sn_ok}")
|
||||
print("save to database ...")
|
||||
save_new_sn_to_db(session, product_name, new_sn)
|
||||
print("save sn ok")
|
||||
updated_last_sn = get_last_sn(session, product_name)
|
||||
print("Updated sn for product", product_name, "is:", updated_last_sn)
|
|
@ -0,0 +1,163 @@
|
|||
/** \file
|
||||
* \brief EEprom tool for Simple Open EtherCAT master
|
||||
*
|
||||
* Usage : eepromtool ifname slave OPTION fname|alias
|
||||
* ifname is NIC interface, f.e. eth0
|
||||
* slave = slave number in EtherCAT order 1..n
|
||||
* -r read EEPROM, output binary format
|
||||
* -ri read EEPROM, output Intel Hex format
|
||||
* -w write EEPROM, input binary format
|
||||
* -wi write EEPROM, input Intel Hex format
|
||||
* -i display EEPROM information
|
||||
* -walias write slave alias in EEPROM
|
||||
*
|
||||
* (c)Arthur Ketels 2010-2012
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eceeprom.h"
|
||||
#include "ethercat.h"
|
||||
|
||||
void show_help(void)
|
||||
{
|
||||
ec_adaptert *adapter = NULL;
|
||||
|
||||
printf("Usage: eceeprom ifname [slaveID [OPTION [fname|alias|serial_no]]]\n");
|
||||
printf("ifname = name of the network interface, e.g., eth0\n");
|
||||
printf("slaveID = slave number in EtherCAT order (1..n)\n");
|
||||
printf("Options:\n");
|
||||
printf("(no slaveID & option) Display slaves count\n");
|
||||
printf(" -i Display EEPROM information\n");
|
||||
printf(" -wa Write slave alias in decimal format\n");
|
||||
printf(" -wah Write slave alias in hexadecimal format\n");
|
||||
printf(" -wsn Write serial number in decimal format\n");
|
||||
printf(" -wsnh Write serial number in hexadecimal format\n");
|
||||
printf(" -r Read EEPROM and output in binary format\n");
|
||||
printf(" -ri Read EEPROM and output in Intel Hex format\n");
|
||||
printf(" -w Write EEPROM using binary input format\n");
|
||||
printf(" -wi Write EEPROM using Intel Hex input format\n");
|
||||
printf("Exaple:\n");
|
||||
printf(" eceeprom eth0 -- Display slaves count\n");
|
||||
printf(" eceeprom eth0 2 -wa 12345 -- Write slave 2 alias '12345'\n");
|
||||
|
||||
printf("\nAvailable adapters:\n");
|
||||
adapter = ec_find_adapters();
|
||||
while (adapter != NULL)
|
||||
{
|
||||
printf(" - %s (%s)\n", adapter->name, adapter->desc);
|
||||
adapter = adapter->next;
|
||||
}
|
||||
ec_free_adapters(adapter);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc = 0;
|
||||
char *option = NULL;
|
||||
char *val = NULL;
|
||||
int slave = 0;
|
||||
int slaveCount = 0;
|
||||
if (argc < 2)
|
||||
{
|
||||
goto __help;
|
||||
}
|
||||
|
||||
char *ifname = argv[1];
|
||||
|
||||
printf("SOEM (Simple Open EtherCAT Master)\nEEPROM tool\n");
|
||||
/* initialise SOEM, bind socket to ifname */
|
||||
if (ec_init(ifname) <= 0)
|
||||
{
|
||||
printf("No socket connection on %s\nExcecute as root\n", ifname);
|
||||
return -1;
|
||||
}
|
||||
printf("ec_init on %s succeeded.\n", ifname);
|
||||
slaveCount = ecGetSlaveCount();
|
||||
if (slaveCount < 1)
|
||||
{
|
||||
printf("No slaves found!\n");
|
||||
rc = -1;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
printf("Found %d slave(s)\n", slaveCount);
|
||||
|
||||
if (argc >= 3)
|
||||
{
|
||||
slave = atoi(argv[2]);
|
||||
}
|
||||
else // argc == 2
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
if ((slave > ec_slavecount) || (slave <= 0))
|
||||
{
|
||||
printf("Slave ID (%d) outside range.\n", slave);
|
||||
rc = -1;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 4:
|
||||
if (strcmp(argv[3], "-i") != 0)
|
||||
{
|
||||
goto __help;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case 3:
|
||||
ecShowInfo(slave, true);
|
||||
break;
|
||||
case 5:
|
||||
val = argv[4];
|
||||
option = argv[3];
|
||||
|
||||
if (strcmp(option, "-r") == 0)
|
||||
rc = ecEepromToFile(slave, val, false);
|
||||
else if (strcmp(option, "-ri") == 0)
|
||||
rc = ecEepromToFile(slave, val, true);
|
||||
else if (strcmp(option, "-w") == 0)
|
||||
rc = ecFileToEeprom(slave, val, false, 0);
|
||||
else if (strcmp(option, "-wi") == 0)
|
||||
rc = ecFileToEeprom(slave, val, true, 0);
|
||||
else if (strcmp(option, "-wa") == 0)
|
||||
{
|
||||
uint16_t alias = (uint16)strtoul(val, NULL, 10);
|
||||
rc = ecWriteAlias(slave, alias);
|
||||
}
|
||||
else if (strcmp(option, "-wah") == 0)
|
||||
{
|
||||
uint16_t alias = (uint16)strtoul(val, NULL, 16);
|
||||
rc = ecWriteAlias(slave, alias);
|
||||
}
|
||||
else if (strcmp(option, "-wsn") == 0)
|
||||
{
|
||||
int32_t sn = strtol(val, NULL, 10);
|
||||
rc = ecWriteSN(slave, sn);
|
||||
}
|
||||
else if (strcmp(option, "-wsnh") == 0)
|
||||
{
|
||||
int32_t sn =(int32_t) strtoul(val, NULL, 16);
|
||||
rc = ecWriteSN(slave, sn);
|
||||
}
|
||||
else
|
||||
goto __help;
|
||||
break;
|
||||
default:
|
||||
goto __help;
|
||||
break;
|
||||
}
|
||||
goto __exit;
|
||||
|
||||
__help:
|
||||
show_help();
|
||||
|
||||
__exit:
|
||||
printf("End, close socket\n");
|
||||
/* stop SOEM, close socket */
|
||||
ec_close();
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
#!/root/venv/bin/python
|
||||
|
||||
import sys
|
||||
from ctypes import *
|
||||
from database import *
|
||||
from sn import *
|
||||
|
||||
|
||||
ll = cdll.LoadLibrary
|
||||
# ece = ll("../../../build/test/linux/eceeprom/libeceeprom.so")
|
||||
ece = ll("../lib/libeceeprom.so")
|
||||
|
||||
|
||||
def get_new_sn(
|
||||
ece, session, slave_id: int, product_name: str, prefix: int, is_force: bool
|
||||
):
|
||||
if not is_force:
|
||||
# check origin sn
|
||||
origin_sn = ece.ecEepromGetSN(slave_id)
|
||||
# origin_sn = 0 # 强制写 SN
|
||||
print(f"Slave {slave_id}: Origin SN = {origin_sn}")
|
||||
if (
|
||||
origin_sn != 0
|
||||
# and origin_sn != 0xFFFFFFFF
|
||||
and sn_is_exist(session, product_name, origin_sn)
|
||||
):
|
||||
print(f"SN ({origin_sn}) is exist. Do NOT update SN")
|
||||
return False, origin_sn
|
||||
# new sn
|
||||
last_sn_ = last_sn = get_last_sn(session, product_name)
|
||||
sn_ok = False
|
||||
new_sn = 0
|
||||
while not sn_ok:
|
||||
new_sn = generate_sn(last_sn_, prefix)
|
||||
sn_ok = not sn_is_exist(session, product_name, new_sn)
|
||||
print(
|
||||
"last sn = %d,new SN %d is %s"
|
||||
% (last_sn_, new_sn, "OK" if sn_ok else "exist")
|
||||
)
|
||||
last_sn_ = new_sn
|
||||
print(f"id: {slave_id}, last sn: {last_sn}, new sn : {new_sn}, prefix: {prefix}")
|
||||
return True, new_sn
|
||||
|
||||
|
||||
def write_multi_eeprom(
|
||||
count: int, session, product_name: str, eeprome_file: str, is_force: bool
|
||||
):
|
||||
product_code_str, prefix_str = get_product_info(session, product_name)
|
||||
prefix = None
|
||||
if prefix_str is not None and prefix_str != "":
|
||||
prefix = int(prefix_str)
|
||||
product_code = None
|
||||
if product_code_str is not None and product_code_str != "":
|
||||
product_code = int(product_code_str)
|
||||
|
||||
# 当从机数量大于1时,不写最后一个
|
||||
if count == 1:
|
||||
count = 2
|
||||
for i in range(1, count):
|
||||
print(f"Write slave EEPROM #{i} :\n")
|
||||
is_new_sn, new_sn = get_new_sn(session, i, product_name, prefix, is_force)
|
||||
|
||||
is_eeprom_initialized = False
|
||||
if not is_force:
|
||||
e_product_code = ece.ecEepromGetProductCode(i)
|
||||
# EEPROM 未初始化
|
||||
if e_product_code == product_code:
|
||||
is_eeprom_initialized = True
|
||||
print(
|
||||
f"Origin product code is {e_product_code}. Is initialized. Do NOT need update EEPROM"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
"Origin product code is %d.Do not matched(%d). Is NOT initialized"
|
||||
% (e_product_code, product_code)
|
||||
)
|
||||
|
||||
rc = 0
|
||||
if is_eeprom_initialized:
|
||||
if is_new_sn and new_sn != 0 and new_sn != -1:
|
||||
rc = ece.ecWriteSN(c_int(i), c_uint32(new_sn))
|
||||
else:
|
||||
print(f"i ={i}, eeprom_file:{eeprome_file},new_sn: {new_sn}")
|
||||
rc = ece.ecFileToEeprom(
|
||||
c_int(i), c_char_p(eeprome_file), c_bool(False), c_uint(new_sn)
|
||||
)
|
||||
if rc > 0:
|
||||
save_new_sn_to_db(session, product_name, new_sn) # update database
|
||||
print("\n")
|
||||
|
||||
|
||||
def main():
|
||||
is_force = False
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "-force":
|
||||
is_force = True
|
||||
|
||||
ifname = b"enp3s0f1"
|
||||
if ece.ec_init(c_char_p(ifname)) <= 0:
|
||||
print("No socket connection on %s\nExcecute as root\n" % ifname)
|
||||
return -1
|
||||
print("ec_init on %s succeeded.\n" % ifname)
|
||||
# Get the number of slaves
|
||||
slaveCount = ece.ecGetSlaveCount()
|
||||
if slaveCount < 1:
|
||||
print("No slaves found!\n")
|
||||
ece.ec_close()
|
||||
return -1
|
||||
print("Found %d slave(s)\n" % slaveCount)
|
||||
|
||||
# # Write the SN
|
||||
session = db_init()
|
||||
|
||||
eeprom_file = b"./TJ30-1616DN-EEPROM.bin"
|
||||
|
||||
product_name = "TJ30-1616DN"
|
||||
|
||||
write_multi_eeprom(slaveCount, session, product_name, eeprom_file, is_force)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,103 @@
|
|||
#!/root/venv/bin/python
|
||||
|
||||
import sys
|
||||
from ctypes import *
|
||||
from database import *
|
||||
from sn import *
|
||||
|
||||
|
||||
ll = cdll.LoadLibrary
|
||||
# ece = ll("../../../build/test/linux/eceeprom/libeceeprom.so")
|
||||
ece = ll("../lib/libeceeprom.so")
|
||||
|
||||
# 输入一个SN(当输入为空时,该sn为0,非字数时,重新输入), 返回SN(int)
|
||||
def input_one_sn():
|
||||
sn = input("请输入SN值(空,则不修改 SN): ")
|
||||
if sn == "":
|
||||
return 0
|
||||
else:
|
||||
try:
|
||||
return int("142404"+sn)
|
||||
except ValueError:
|
||||
print("输入的不是数字,请重新输入。")
|
||||
return input_one_sn()
|
||||
|
||||
# 输入SN(当输入为空时,该sn为0), 返回SN列表, count = 1 时,读取一个SN,count > 1 时,读取 count -1 个SN
|
||||
def input_sn(count: int):
|
||||
sn = []
|
||||
if count == 1:
|
||||
sn.append(input_one_sn())
|
||||
elif count > 1:
|
||||
for i in range(1, count):
|
||||
print(f"#{i} -> ",end='')
|
||||
sn.append(input_one_sn())
|
||||
return sn
|
||||
|
||||
def write_multi_eeprom(
|
||||
count: int, sn, eeprome_file: str, is_force: bool
|
||||
):
|
||||
product_code = 66048 # for TJ30-1616DN
|
||||
|
||||
# 当从机数量大于1时,不写最后一个
|
||||
if count == 1:
|
||||
count = 2
|
||||
for i in range(1, count):# 1 ~ count-1
|
||||
print(f"Write slave EEPROM #{i} :\n")
|
||||
|
||||
is_eeprom_initialized = False
|
||||
if not is_force:# 检测是否已经初始化
|
||||
e_product_code = ece.ecEepromGetProductCode(i)
|
||||
# EEPROM 未初始化
|
||||
if e_product_code == product_code:
|
||||
is_eeprom_initialized = True
|
||||
print(
|
||||
f"Origin product code is {e_product_code}. Is initialized. Do NOT need update EEPROM"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
"Origin product code is %d.Do not matched(%d). Is NOT initialized"
|
||||
% (e_product_code, product_code)
|
||||
)
|
||||
|
||||
rc = 0
|
||||
if sn[i-1] == 0 or sn[i-1] == -1:
|
||||
print("SN is 0 or -1. Do NOT need update EEPROM")
|
||||
continue
|
||||
if is_eeprom_initialized:
|
||||
if is_force:
|
||||
rc = ece.ecWriteSN(c_int(i), c_uint32(sn[i-1]))
|
||||
else:
|
||||
print(f"i ={i}, eeprom_file:{eeprome_file},sn: {sn[i-1]}")
|
||||
rc = ece.ecFileToEeprom(
|
||||
c_int(i), c_char_p(eeprome_file), c_bool(False), c_uint(sn[i-1])
|
||||
)
|
||||
|
||||
print("\n")
|
||||
|
||||
|
||||
def main():
|
||||
is_force = False
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "-force":
|
||||
is_force = True
|
||||
|
||||
ifname = b"enp3s0f1"
|
||||
if ece.ec_init(c_char_p(ifname)) <= 0:
|
||||
print("No socket connection on %s\nExcecute as root\n" % ifname)
|
||||
return -1
|
||||
print("ec_init on %s succeeded.\n" % ifname)
|
||||
# Get the number of slaves
|
||||
slaveCount = ece.ecGetSlaveCount()
|
||||
if slaveCount < 1:
|
||||
print("No slaves found!\n")
|
||||
ece.ec_close()
|
||||
return -1
|
||||
print("Found %d slave(s)\n" % slaveCount)
|
||||
|
||||
# # Write the SN
|
||||
eeprom_file = b"./TJ30-1616DN-EEPROM.bin"
|
||||
sn = input_sn(slaveCount)
|
||||
write_multi_eeprom(slaveCount, sn, eeprom_file, is_force)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,569 @@
|
|||
/** \file
|
||||
* \brief EEprom tool for Simple Open EtherCAT master
|
||||
*
|
||||
* Usage : eepromtool ifname slave OPTION fname|alias
|
||||
* ifname is NIC interface, f.e. eth0
|
||||
* slave = slave number in EtherCAT order 1..n
|
||||
* -r read EEPROM, output binary format
|
||||
* -ri read EEPROM, output Intel Hex format
|
||||
* -w write EEPROM, input binary format
|
||||
* -wi write EEPROM, input Intel Hex format
|
||||
* -i display EEPROM information
|
||||
* -walias write slave alias in EEPROM
|
||||
*
|
||||
* (c)Arthur Ketels 2010-2012
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eceeprom.h"
|
||||
#include "ethercat.h"
|
||||
|
||||
#define MAXSLENGTH 256
|
||||
#define IHEXLENGTH 0x20
|
||||
#define CRCBUF 14
|
||||
|
||||
uint8 ebuf[MAXBUF];
|
||||
|
||||
static void calc_crc(uint8_t *crc, uint8_t b)
|
||||
{
|
||||
int j;
|
||||
*crc ^= b;
|
||||
for (j = 0; j <= 7; j++)
|
||||
{
|
||||
if (*crc & 0x80)
|
||||
*crc = (*crc << 1) ^ 0x07;
|
||||
else
|
||||
*crc = (*crc << 1);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t SIIcrc(uint8_t *buf)
|
||||
{
|
||||
int i;
|
||||
uint8_t crc;
|
||||
|
||||
crc = 0xff;
|
||||
for (i = 0; i <= 13; i++)
|
||||
{
|
||||
calc_crc(&crc, *(buf++));
|
||||
}
|
||||
return (uint16_t)crc;
|
||||
}
|
||||
|
||||
int ecBufferFromBin(const char *fname, int *length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int cc = 0, c;
|
||||
|
||||
fp = fopen(fname, "rb");
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
while (((c = fgetc(fp)) != EOF) && (cc < MAXBUF))
|
||||
ebuf[cc++] = (uint8_t)c;
|
||||
*length = cc;
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecBufferFromIntelHex(const char *fname, int *start, int *length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int c, sc, retval = 1;
|
||||
int ll, ladr, lt, sn, i, lval;
|
||||
int hstart, hlength, sum;
|
||||
char sline[MAXSLENGTH];
|
||||
|
||||
fp = fopen(fname, "r");
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
hstart = MAXBUF;
|
||||
hlength = 0;
|
||||
sum = 0;
|
||||
do
|
||||
{
|
||||
memset(sline, 0x00, MAXSLENGTH);
|
||||
sc = 0;
|
||||
while (((c = fgetc(fp)) != EOF) && (c != 0x0A) && (sc < (MAXSLENGTH - 1)))
|
||||
sline[sc++] = (uint8_t)c;
|
||||
if ((c != EOF) && ((sc < 11) || (sline[0] != ':')))
|
||||
{
|
||||
c = EOF;
|
||||
retval = 0;
|
||||
printf("Invalid Intel Hex format.\n");
|
||||
}
|
||||
if (c != EOF)
|
||||
{
|
||||
sn = sscanf(sline, ":%2x%4x%2x", &ll, &ladr, <);
|
||||
if ((sn == 3) && ((ladr + ll) <= MAXBUF) && (lt == 0))
|
||||
{
|
||||
sum = ll + (ladr >> 8) + (ladr & 0xff) + lt;
|
||||
if (ladr < hstart)
|
||||
hstart = ladr;
|
||||
for (i = 0; i < ll; i++)
|
||||
{
|
||||
sn = sscanf(&sline[9 + (i << 1)], "%2x", &lval);
|
||||
ebuf[ladr + i] = (uint8_t)lval;
|
||||
sum += (uint8_t)lval;
|
||||
}
|
||||
if (((ladr + ll) - hstart) > hlength)
|
||||
hlength = (ladr + ll) - hstart;
|
||||
sum = (0x100 - sum) & 0xff;
|
||||
sn = sscanf(&sline[9 + (i << 1)], "%2x", &lval);
|
||||
if (!sn || ((sum - lval) != 0))
|
||||
{
|
||||
c = EOF;
|
||||
retval = 0;
|
||||
printf("Invalid checksum.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (c != EOF);
|
||||
if (retval)
|
||||
{
|
||||
*length = hlength;
|
||||
*start = hstart;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int ecBufferToBin(const char *fname, int length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int cc;
|
||||
|
||||
fp = fopen(fname, "wb");
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Can not write to file %s\n", fname);
|
||||
return 0;
|
||||
}
|
||||
for (cc = 0; cc < length; cc++)
|
||||
fputc(ebuf[cc], fp);
|
||||
fclose(fp);
|
||||
return length;
|
||||
}
|
||||
|
||||
int ecBufferToIntelHex(const char *fname, int length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int cc = 0, ll, sum, i;
|
||||
|
||||
fp = fopen(fname, "w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Can not write to file %s\n", fname);
|
||||
return 0;
|
||||
}
|
||||
while (cc < length)
|
||||
{
|
||||
ll = length - cc;
|
||||
if (ll > IHEXLENGTH)
|
||||
ll = IHEXLENGTH;
|
||||
sum = ll + (cc >> 8) + (cc & 0xff);
|
||||
fprintf(fp, ":%2.2X%4.4X00", ll, cc);
|
||||
for (i = 0; i < ll; i++)
|
||||
{
|
||||
fprintf(fp, "%2.2X", ebuf[cc + i]);
|
||||
sum += ebuf[cc + i];
|
||||
}
|
||||
fprintf(fp, "%2.2X\n", (0x100 - sum) & 0xff);
|
||||
cc += ll;
|
||||
}
|
||||
fprintf(fp, ":00000001FF\n");
|
||||
fclose(fp);
|
||||
return length;
|
||||
}
|
||||
|
||||
int ecEepromRead(int slave, int start, int length)
|
||||
{
|
||||
int i, ainc = 4;
|
||||
uint16_t estat, aiadr;
|
||||
uint32_t b4;
|
||||
uint64_t b8;
|
||||
uint8_t eepctl;
|
||||
|
||||
if ((ec_slavecount >= slave) && (slave > 0) && ((start + length) <= MAXBUF))
|
||||
{
|
||||
aiadr = 1 - slave;
|
||||
eepctl = 2;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl,
|
||||
EC_TIMEOUTRET); /* force Eeprom from PDI */
|
||||
eepctl = 0;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl,
|
||||
EC_TIMEOUTRET); /* set Eeprom to master */
|
||||
|
||||
estat = 0x0000;
|
||||
aiadr = 1 - slave;
|
||||
ec_APRD(aiadr, ECT_REG_EEPSTAT, sizeof(estat), &estat,
|
||||
EC_TIMEOUTRET); /* read eeprom status */
|
||||
estat = etohs(estat);
|
||||
if (estat & EC_ESTAT_R64)
|
||||
{
|
||||
ainc = 8;
|
||||
for (i = start; i < (start + length); i += ainc)
|
||||
{
|
||||
b8 = ec_readeepromAP(aiadr, i >> 1, EC_TIMEOUTEEP);
|
||||
ebuf[i] = b8 & 0xFF;
|
||||
ebuf[i + 1] = (b8 >> 8) & 0xFF;
|
||||
ebuf[i + 2] = (b8 >> 16) & 0xFF;
|
||||
ebuf[i + 3] = (b8 >> 24) & 0xFF;
|
||||
ebuf[i + 4] = (b8 >> 32) & 0xFF;
|
||||
ebuf[i + 5] = (b8 >> 40) & 0xFF;
|
||||
ebuf[i + 6] = (b8 >> 48) & 0xFF;
|
||||
ebuf[i + 7] = (b8 >> 56) & 0xFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = start; i < (start + length); i += ainc)
|
||||
{
|
||||
b4 = ec_readeepromAP(aiadr, i >> 1, EC_TIMEOUTEEP) & 0xFFFFFFFF;
|
||||
ebuf[i] = b4 & 0xFF;
|
||||
ebuf[i + 1] = (b4 >> 8) & 0xFF;
|
||||
ebuf[i + 2] = (b4 >> 16) & 0xFF;
|
||||
ebuf[i + 3] = (b4 >> 24) & 0xFF;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ecEepromWrite(int slave, int start, int wlength)
|
||||
{
|
||||
int i, dc = 0;
|
||||
uint16_t aiadr, *wbuf;
|
||||
uint8_t eepctl;
|
||||
|
||||
if ((ec_slavecount >= slave) && (slave > 0) && ((start + wlength) * 2 <= MAXBUF))
|
||||
{
|
||||
aiadr = 1 - slave;
|
||||
eepctl = 2;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl,
|
||||
EC_TIMEOUTRET); /* force Eeprom from PDI */
|
||||
eepctl = 0;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl,
|
||||
EC_TIMEOUTRET); /* set Eeprom to master */
|
||||
|
||||
aiadr = 1 - slave;
|
||||
wbuf = (uint16_t *)&ebuf[0];
|
||||
for (i = start; i < (start + wlength); i++)
|
||||
{
|
||||
ec_writeeepromAP(aiadr, i, *(wbuf + i), EC_TIMEOUTEEP);
|
||||
if (++dc >= 100)
|
||||
{
|
||||
dc = 0;
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ecGetESize(void)
|
||||
{
|
||||
uint16_t *wbuf = (uint16_t *)&ebuf[0];
|
||||
int esize = (*(wbuf + 0x3E) + 1) * 128;
|
||||
if (esize > MAXBUF)
|
||||
{
|
||||
esize = MAXBUF;
|
||||
}
|
||||
return esize;
|
||||
}
|
||||
|
||||
int ecEepromToBuffer(int slave, bool isFull)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ecEepromRead(slave, 0x0000, MINBUF); // read first 128 bytes
|
||||
|
||||
if (isFull && rc > 0)
|
||||
{
|
||||
uint16_t esize = ecGetESize();
|
||||
if (esize > MINBUF)
|
||||
rc += ecEepromRead(slave, MINBUF, esize - MINBUF); // read reminder}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#if 0
|
||||
void show_hex(uint8_t *buff, int len)
|
||||
{
|
||||
int i = 0;
|
||||
uint16_t a = 0;
|
||||
printf("addr 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\n");
|
||||
for (; i < len - 16; i += 16, a += 16)
|
||||
{
|
||||
printf("%04X %02X %02X %02X %02X %02X %02X %02X %02X "
|
||||
"%02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
a, buff[i], buff[i + 1], buff[i + 2], buff[i + 3], buff[i + 4], buff[i + 5],
|
||||
buff[i + 6], buff[i + 7], buff[i + 8], buff[i + 9], buff[i + 10], buff[i + 11],
|
||||
buff[i + 12], buff[i + 13], buff[i + 14], buff[i + 15]);
|
||||
}
|
||||
if (i == len)
|
||||
{
|
||||
return;
|
||||
}
|
||||
printf("%04X", a);
|
||||
for (int j = 0; i < len; i++, j++)
|
||||
{
|
||||
if (j == 8)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
printf(" %02X", buff[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
int ecEepromWriteAlias(int slave, uint16_t alias, uint16_t *crc)
|
||||
{
|
||||
int ret;
|
||||
ret = ecEepromToBuffer(slave, false);
|
||||
if (ret <= 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16 *wbuf = (uint16 *)&ebuf[0];
|
||||
*(wbuf + 0x04) = alias;
|
||||
*crc = *(wbuf + 0x07) = SIIcrc(&ebuf[0]);
|
||||
|
||||
ret = ecEepromWrite(slave, 0x00, 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t ecEepromGetProductCode(int slave)
|
||||
{
|
||||
int ret;
|
||||
ret = ecEepromToBuffer(slave, true);
|
||||
if (ret <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint16 *wbuf = (uint16 *)&ebuf[0];
|
||||
return ((uint32_t) * (wbuf + 0x0B)) << 16 | *(wbuf + 0x0A);
|
||||
}
|
||||
|
||||
|
||||
int32_t ecEepromGetSN(int slave)
|
||||
{
|
||||
int ret;
|
||||
ret = ecEepromToBuffer(slave, true);
|
||||
if (ret <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint16 *wbuf = (uint16 *)&ebuf[0];
|
||||
return ((int32_t) * (wbuf + 0x0F)) << 16 | *(wbuf + 0x0E);
|
||||
}
|
||||
|
||||
void ecUpdateSNBuff(int32_t sn)
|
||||
{
|
||||
uint16 *wbuf = (uint16 *)&ebuf[0];
|
||||
*(wbuf + 0x0E) = (uint16_t)((uint32_t)sn & 0xffff);
|
||||
*(wbuf + 0x0F) = (uint16_t)((uint32_t)sn >> 16);
|
||||
}
|
||||
|
||||
int ecEepromWriteSN(int slave, int32_t sn)
|
||||
{
|
||||
int ret;
|
||||
ret = ecEepromToBuffer(slave, true);
|
||||
if (ret <= 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
ecUpdateSNBuff(sn);
|
||||
return ecEepromWrite(slave, 0x0E, 2);
|
||||
}
|
||||
|
||||
int ecGetSlaveCount(void)
|
||||
{
|
||||
int w = 0x0000;
|
||||
/* detect number of slaves */
|
||||
int wkc = ec_BRD(0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE);
|
||||
if (wkc > 0)
|
||||
{
|
||||
ec_slavecount = wkc;
|
||||
return wkc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ecBufferShowInfo(int slave, bool isDetails)
|
||||
{
|
||||
uint16_t crc = SIIcrc(&ebuf[0]);
|
||||
uint16 *wbuf = (uint16 *)&ebuf[0];
|
||||
int esize = ecGetESize();
|
||||
|
||||
printf("Slave %d data\n", slave);
|
||||
printf(" Vendor ID : 0x%8.8X(%u)\n", *(uint32_t *)(wbuf + 0x08),
|
||||
*(uint32_t *)(wbuf + 0x08));
|
||||
printf(" Product Code : 0x%8.8X(%u)\n", *(uint32_t *)(wbuf + 0x0A),
|
||||
*(uint32_t *)(wbuf + 0x0A));
|
||||
printf(" Revision Number : 0x%8.8X(%u)\n", *(uint32_t *)(wbuf + 0x0C),
|
||||
*(uint32_t *)(wbuf + 0x0C));
|
||||
printf(" Serial Number : 0x%8.8X(%u)\n", *(uint32_t *)(wbuf + 0x0E),
|
||||
*(uint32_t *)(wbuf + 0x0E));
|
||||
printf(" Config Alias : 0x%4.4X(%u)\n", *(wbuf + 0x04), *(wbuf + 0x04));
|
||||
printf(" Checksum : 0x%2.2X (%s)\n", *(wbuf + 0x07),
|
||||
(*(wbuf + 0x07) == crc) ? "Match" : "NOT Match");
|
||||
printf(" calculated : 0x%2.2X\n", crc);
|
||||
|
||||
if (isDetails)
|
||||
{
|
||||
printf(" PDI Control : 0x%4.4X(%u)\n", *(wbuf + 0x00), *(wbuf + 0x00));
|
||||
printf(" PDI Config : 0x%4.4X(%u)\n", *(wbuf + 0x01), *(wbuf + 0x01));
|
||||
printf(" Mailbox Protocol : 0x%4.4X\n", *(wbuf + 0x1C));
|
||||
printf(" EEPROM Size : 0x%4.4X = %d bytes\n", *(wbuf + 0x3E), esize);
|
||||
}
|
||||
printf(" Version : 0x%4.4X(%u)\n", *(wbuf + 0x3F), *(wbuf + 0x3F));
|
||||
// show_hex(ebuf, 32);
|
||||
}
|
||||
|
||||
void ecShowInfo(int slave, bool isDetails)
|
||||
{
|
||||
osal_usleep(1000);
|
||||
int ret = ecEepromToBuffer(slave, false); // read first 128 bytes
|
||||
if (ret <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ecBufferShowInfo(slave, isDetails);
|
||||
}
|
||||
|
||||
int ecEepromToFile(int slave, const char *fname, bool isHex)
|
||||
{
|
||||
ec_timet tstart, tend, tdif;
|
||||
char *format;
|
||||
int esize;
|
||||
int rc;
|
||||
|
||||
printf("Slave %d:\n", slave);
|
||||
printf("Read data from EEPROM ...\n");
|
||||
tstart = osal_current_time();
|
||||
rc = ecEepromToBuffer(slave, true);
|
||||
if (rc <= 0)
|
||||
{
|
||||
printf("Read Slave %d EEPROM FALL\n", slave);
|
||||
return rc;
|
||||
}
|
||||
tend = osal_current_time();
|
||||
osal_time_diff(&tstart, &tend, &tdif);
|
||||
printf("\nTotal EEPROM read time: %ldms\n", (tdif.usec + (tdif.sec * 1000000L)) / 1000);
|
||||
esize = ecGetESize();
|
||||
if (isHex)
|
||||
{
|
||||
rc = ecBufferToIntelHex(fname, esize);
|
||||
format = "Intel Hex";
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = ecBufferToBin(fname, esize);
|
||||
format = "Binary";
|
||||
}
|
||||
if (rc > 0)
|
||||
{
|
||||
printf("EEPROM data save to file %s in %s format, size %d bytes\n", fname, format, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ecFileToEeprom(int slave, const char *fname, bool isHex, int32_t sn)
|
||||
{
|
||||
printf("Load file '%s'. Is Hex? %s\n", fname, isHex ? "True" : "False");
|
||||
int rc;
|
||||
int estart = 0;
|
||||
int esize = 0;
|
||||
if (isHex)
|
||||
rc = ecBufferFromIntelHex(fname, &estart, &esize);
|
||||
else
|
||||
rc = ecBufferFromBin(fname, &esize);
|
||||
|
||||
if (rc <= 0)
|
||||
{
|
||||
printf("Load file '%s' FAIL\n", fname);
|
||||
return rc;
|
||||
}
|
||||
if (sn)
|
||||
{
|
||||
printf("Update SN -> %u\n", sn);
|
||||
ecUpdateSNBuff(sn);
|
||||
}
|
||||
// ecBufferShowInfo(slave, true);
|
||||
printf("Busy");
|
||||
fflush(stdout);
|
||||
|
||||
ec_timet tstart = osal_current_time();
|
||||
estart = 0;
|
||||
rc = ecEepromWrite(slave, estart, esize / 2);
|
||||
|
||||
if (rc > 0)
|
||||
{
|
||||
ec_timet tend = osal_current_time();
|
||||
ec_timet tdif = {0};
|
||||
osal_time_diff(&tstart, &tend, &tdif);
|
||||
printf("\nTotal EEPROM write time :%ldms\n", (tdif.usec + (tdif.sec * 1000000L)) / 1000);
|
||||
ecShowInfo(slave, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error reading file, abort.\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ecWriteAlias(int slave, uint16_t alias)
|
||||
{
|
||||
uint16_t crc;
|
||||
int rc = ecEepromWriteAlias(slave, alias, &crc);
|
||||
if (rc > 0)
|
||||
{
|
||||
printf("Alias %d (HEX: %4.4X) , CRC = %02X written successfully to slave %d\n", alias,
|
||||
alias, crc, slave);
|
||||
ecShowInfo(slave, false);
|
||||
}
|
||||
else if (rc < 0)
|
||||
{
|
||||
printf("Could not read slave EEPROM");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Alias not written\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ecWriteSN(int slave, int32_t sn)
|
||||
{
|
||||
printf("Write slave %d SN %u ...\n", slave, sn);
|
||||
int rc = ecEepromWriteSN(slave, sn);
|
||||
if (rc > 0)
|
||||
{
|
||||
printf("SN %d (HEX: %8.8X) written successfully to slave %d\n", sn, sn, slave);
|
||||
ecShowInfo(slave, false);
|
||||
}
|
||||
else if (rc < 0)
|
||||
{
|
||||
printf("Could not read slave EEPROM\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("SN not written\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef __EC_EEPROM_H__
|
||||
#define __EC_EEPROM_H__
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAXBUF 524288
|
||||
#define MINBUF 128
|
||||
|
||||
int ecBufferFromBin(const char *fname, int *length);
|
||||
int ecBufferFromIntelHex(const char *fname, int *start, int *length);
|
||||
int ecBufferToBin(const char *fname, int length);
|
||||
int ecBufferToIntelHex(const char *fname, int length);
|
||||
int ecEepromRead(int slave, int start, int length);
|
||||
int ecEepromWrite(int slave, int start, int length);
|
||||
int ecEepromWriteAlias(int slave, uint16_t alias, uint16_t *crc);
|
||||
void ecUpdateSNBuff(int32_t sn);
|
||||
int ecEepromWriteSN(int slave, int32_t sn);
|
||||
int32_t ecEepromGetSN(int slave);
|
||||
int ecGetSlaveCount(void);
|
||||
int ecGetESize(void);
|
||||
void ecShowInfo(int slave, bool isDetails);
|
||||
void ecBufferShowInfo(int slave, bool isDetails);
|
||||
int ecEepromToBuffer(int slave, bool isFull);
|
||||
int ecEepromToFile(int slave, const char *fname, bool isHex);
|
||||
int ecFileToEeprom(int slave, const char *fname, bool isHex, int32_t sn);
|
||||
int ecWriteAlias(int slave, uint16_t alias);
|
||||
int ecWriteSN(int slave, int32_t sn);
|
||||
uint32_t ecEepromGetProductCode(int slave);
|
||||
#endif /* __EC_EEPROM_H__ */
|
|
@ -0,0 +1,64 @@
|
|||
#!/bin/env python3
|
||||
|
||||
import datetime, sys
|
||||
import Verhoeff
|
||||
from database import *
|
||||
import csv
|
||||
|
||||
|
||||
# sn 的组成:
|
||||
# [0 1] [2 3] [4 5] [6 7 8] [9]
|
||||
# [设备ID] [ 年 ] [ 月 ] [顺序号] [校验码]
|
||||
# sn 10位十进制数据
|
||||
# 顺序号每月开始重置为 001
|
||||
# 校验码算法 Verhoeff
|
||||
def generate_sn(last_sn: int, prefix: int = None) -> int:
|
||||
device_id = last_sn // 100000000
|
||||
curr_device_id = device_id if prefix is None else prefix
|
||||
|
||||
today = datetime.datetime.today()
|
||||
# today = datetime.datetime(2023,12,1,0,0,0)
|
||||
curr_year = today.year % 100
|
||||
curr_month = today.month
|
||||
|
||||
year = last_sn // 1000000 % 100
|
||||
month = last_sn // 10000 % 100
|
||||
|
||||
sequence_num = last_sn // 10 % 1000
|
||||
|
||||
if year != curr_year or month != curr_month or device_id != curr_device_id:
|
||||
sequence_num = 1
|
||||
year = curr_year
|
||||
month = curr_month
|
||||
else:
|
||||
sequence_num += 1
|
||||
|
||||
new_sn_without_check = (
|
||||
curr_device_id * 10000000 + year * 100000 + month * 1000 + sequence_num
|
||||
)
|
||||
new_check = Verhoeff.checksum(str(new_sn_without_check))
|
||||
return new_sn_without_check * 10 + new_check
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 4:
|
||||
print("python sn.py last_sn num csv_file")
|
||||
else:
|
||||
csv_file = sys.argv[3]
|
||||
last_sn = int(sys.argv[1])
|
||||
num = int(sys.argv[2])
|
||||
print(f"last SN: {last_sn}, num: {num}")
|
||||
sn_list = []
|
||||
for i in range(1, num + 1):
|
||||
sn = generate_sn(last_sn)
|
||||
row = [i, sn]
|
||||
sn_list.append(row)
|
||||
last_sn = sn
|
||||
print(sn_list)
|
||||
with open(csv_file, "w", encoding="utf-8", newline="") as f:
|
||||
csv_writer = csv.writer(f)
|
||||
name = ["ID", "SN"]
|
||||
csv_writer.writerow(name)
|
||||
csv_writer.writerows(sn_list)
|
||||
print(f"写入{csv_file}成功")
|
||||
f.close()
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/env bash
|
||||
|
||||
dir=$(cd "$(dirname $0)";pwd)
|
||||
${dir}/ec_eeprom.py
|
||||
|
||||
echo 请先断电,再通电
|
||||
read -n 1 -s -r -p "按任意键继续..."
|
||||
sleep 2
|
||||
# ${dir}/ecslaveinfo enp3s0f1
|
||||
${dir}/tj30_test enp3s0f1
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
set(SOURCES ecslaveinfo.c)
|
||||
add_executable(ecslaveinfo ${SOURCES})
|
||||
target_link_libraries(ecslaveinfo soem)
|
||||
install(TARGETS ecslaveinfo DESTINATION bin)
|
|
@ -711,7 +711,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
printf("Usage: slaveinfo ifname [options]\nifname = eth0 for example\nOptions :\n -sdo : print SDO info\n -map : print mapping\n");
|
||||
printf("Usage: ecslaveinfo ifname [options]\nifname = eth0 for example\nOptions :\n -sdo : print SDO info\n -map : print mapping\n");
|
||||
|
||||
printf ("Available adapters\n");
|
||||
adapter = ec_find_adapters ();
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
set(SOURCES eepromtool.c)
|
||||
add_executable(eepromtool ${SOURCES})
|
||||
target_link_libraries(eepromtool soem)
|
||||
install(TARGETS eepromtool DESTINATION bin)
|
|
@ -1,484 +0,0 @@
|
|||
/** \file
|
||||
* \brief EEprom tool for Simple Open EtherCAT master
|
||||
*
|
||||
* Usage : eepromtool ifname slave OPTION fname|alias
|
||||
* ifname is NIC interface, f.e. eth0
|
||||
* slave = slave number in EtherCAT order 1..n
|
||||
* -r read EEPROM, output binary format
|
||||
* -ri read EEPROM, output Intel Hex format
|
||||
* -w write EEPROM, input binary format
|
||||
* -wi write EEPROM, input Intel Hex format
|
||||
* -i display EEPROM information
|
||||
* -walias write slave alias in EEPROM
|
||||
*
|
||||
* (c)Arthur Ketels 2010-2012
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ethercat.h"
|
||||
|
||||
#define MAXBUF 524288
|
||||
#define STDBUF 2048
|
||||
#define MINBUF 128
|
||||
#define CRCBUF 14
|
||||
|
||||
#define MODE_NONE 0
|
||||
#define MODE_READBIN 1
|
||||
#define MODE_READINTEL 2
|
||||
#define MODE_WRITEBIN 3
|
||||
#define MODE_WRITEINTEL 4
|
||||
#define MODE_WRITEALIAS 5
|
||||
#define MODE_INFO 6
|
||||
|
||||
#define MAXSLENGTH 256
|
||||
|
||||
uint8 ebuf[MAXBUF];
|
||||
uint8 ob;
|
||||
uint16 ow;
|
||||
int os;
|
||||
int slave;
|
||||
int alias;
|
||||
ec_timet tstart,tend, tdif;
|
||||
int wkc;
|
||||
int mode;
|
||||
char sline[MAXSLENGTH];
|
||||
|
||||
#define IHEXLENGTH 0x20
|
||||
|
||||
void calc_crc(uint8 *crc, uint8 b)
|
||||
{
|
||||
int j;
|
||||
*crc ^= b;
|
||||
for(j = 0; j <= 7 ; j++ )
|
||||
{
|
||||
if(*crc & 0x80)
|
||||
*crc = (*crc << 1) ^ 0x07;
|
||||
else
|
||||
*crc = (*crc << 1);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 SIIcrc(uint8 *buf)
|
||||
{
|
||||
int i;
|
||||
uint8 crc;
|
||||
|
||||
crc = 0xff;
|
||||
for( i = 0 ; i <= 13 ; i++ )
|
||||
{
|
||||
calc_crc(&crc , *(buf++));
|
||||
}
|
||||
return (uint16)crc;
|
||||
}
|
||||
|
||||
int input_bin(char *fname, int *length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int cc = 0, c;
|
||||
|
||||
fp = fopen(fname, "rb");
|
||||
if(fp == NULL)
|
||||
return 0;
|
||||
while (((c = fgetc(fp)) != EOF) && (cc < MAXBUF))
|
||||
ebuf[cc++] = (uint8)c;
|
||||
*length = cc;
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int input_intelhex(char *fname, int *start, int *length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int c, sc, retval = 1;
|
||||
int ll, ladr, lt, sn, i, lval;
|
||||
int hstart, hlength, sum;
|
||||
|
||||
fp = fopen(fname, "r");
|
||||
if(fp == NULL)
|
||||
return 0;
|
||||
hstart = MAXBUF;
|
||||
hlength = 0;
|
||||
sum = 0;
|
||||
do
|
||||
{
|
||||
memset(sline, 0x00, MAXSLENGTH);
|
||||
sc = 0;
|
||||
while (((c = fgetc(fp)) != EOF) && (c != 0x0A) && (sc < (MAXSLENGTH -1)))
|
||||
sline[sc++] = (uint8)c;
|
||||
if ((c != EOF) && ((sc < 11) || (sline[0] != ':')))
|
||||
{
|
||||
c = EOF;
|
||||
retval = 0;
|
||||
printf("Invalid Intel Hex format.\n");
|
||||
}
|
||||
if (c != EOF)
|
||||
{
|
||||
sn = sscanf(sline , ":%2x%4x%2x", &ll, &ladr, <);
|
||||
if ((sn == 3) && ((ladr + ll) <= MAXBUF) && (lt == 0))
|
||||
{
|
||||
sum = ll + (ladr >> 8) + (ladr & 0xff) + lt;
|
||||
if(ladr < hstart) hstart = ladr;
|
||||
for(i = 0; i < ll ; i++)
|
||||
{
|
||||
sn = sscanf(&sline[9 + (i << 1)], "%2x", &lval);
|
||||
ebuf[ladr + i] = (uint8)lval;
|
||||
sum += (uint8)lval;
|
||||
}
|
||||
if(((ladr + ll) - hstart) > hlength)
|
||||
hlength = (ladr + ll) - hstart;
|
||||
sum = (0x100 - sum) & 0xff;
|
||||
sn = sscanf(&sline[9 + (i << 1)], "%2x", &lval);
|
||||
if (!sn || ((sum - lval) != 0))
|
||||
{
|
||||
c = EOF;
|
||||
retval = 0;
|
||||
printf("Invalid checksum.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (c != EOF);
|
||||
if (retval)
|
||||
{
|
||||
*length = hlength;
|
||||
*start = hstart;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int output_bin(char *fname, int length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int cc;
|
||||
|
||||
fp = fopen(fname, "wb");
|
||||
if(fp == NULL)
|
||||
return 0;
|
||||
for (cc = 0 ; cc < length ; cc++)
|
||||
fputc( ebuf[cc], fp);
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int output_intelhex(char *fname, int length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int cc = 0, ll, sum, i;
|
||||
|
||||
fp = fopen(fname, "w");
|
||||
if(fp == NULL)
|
||||
return 0;
|
||||
while (cc < length)
|
||||
{
|
||||
ll = length - cc;
|
||||
if (ll > IHEXLENGTH) ll = IHEXLENGTH;
|
||||
sum = ll + (cc >> 8) + (cc & 0xff);
|
||||
fprintf(fp, ":%2.2X%4.4X00", ll, cc);
|
||||
for (i = 0; i < ll; i++)
|
||||
{
|
||||
fprintf(fp, "%2.2X", ebuf[cc + i]);
|
||||
sum += ebuf[cc + i];
|
||||
}
|
||||
fprintf(fp, "%2.2X\n", (0x100 - sum) & 0xff);
|
||||
cc += ll;
|
||||
}
|
||||
fprintf(fp, ":00000001FF\n");
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eeprom_read(int slave, int start, int length)
|
||||
{
|
||||
int i, ainc = 4;
|
||||
uint16 estat, aiadr;
|
||||
uint32 b4;
|
||||
uint64 b8;
|
||||
uint8 eepctl;
|
||||
|
||||
if((ec_slavecount >= slave) && (slave > 0) && ((start + length) <= MAXBUF))
|
||||
{
|
||||
aiadr = 1 - slave;
|
||||
eepctl = 2;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* force Eeprom from PDI */
|
||||
eepctl = 0;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* set Eeprom to master */
|
||||
|
||||
estat = 0x0000;
|
||||
aiadr = 1 - slave;
|
||||
ec_APRD(aiadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET); /* read eeprom status */
|
||||
estat = etohs(estat);
|
||||
if (estat & EC_ESTAT_R64)
|
||||
{
|
||||
ainc = 8;
|
||||
for (i = start ; i < (start + length) ; i+=ainc)
|
||||
{
|
||||
b8 = ec_readeepromAP(aiadr, i >> 1 , EC_TIMEOUTEEP);
|
||||
ebuf[i] = b8 & 0xFF;
|
||||
ebuf[i+1] = (b8 >> 8) & 0xFF;
|
||||
ebuf[i+2] = (b8 >> 16) & 0xFF;
|
||||
ebuf[i+3] = (b8 >> 24) & 0xFF;
|
||||
ebuf[i+4] = (b8 >> 32) & 0xFF;
|
||||
ebuf[i+5] = (b8 >> 40) & 0xFF;
|
||||
ebuf[i+6] = (b8 >> 48) & 0xFF;
|
||||
ebuf[i+7] = (b8 >> 56) & 0xFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = start ; i < (start + length) ; i+=ainc)
|
||||
{
|
||||
b4 = ec_readeepromAP(aiadr, i >> 1 , EC_TIMEOUTEEP) & 0xFFFFFFFF;
|
||||
ebuf[i] = b4 & 0xFF;
|
||||
ebuf[i+1] = (b4 >> 8) & 0xFF;
|
||||
ebuf[i+2] = (b4 >> 16) & 0xFF;
|
||||
ebuf[i+3] = (b4 >> 24) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eeprom_write(int slave, int start, int length)
|
||||
{
|
||||
int i, dc = 0;
|
||||
uint16 aiadr, *wbuf;
|
||||
uint8 eepctl;
|
||||
|
||||
if((ec_slavecount >= slave) && (slave > 0) && ((start + length) <= MAXBUF))
|
||||
{
|
||||
aiadr = 1 - slave;
|
||||
eepctl = 2;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* force Eeprom from PDI */
|
||||
eepctl = 0;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* set Eeprom to master */
|
||||
|
||||
aiadr = 1 - slave;
|
||||
wbuf = (uint16 *)&ebuf[0];
|
||||
for (i = start ; i < (start + length) ; i+=2)
|
||||
{
|
||||
ec_writeeepromAP(aiadr, i >> 1 , *(wbuf + (i >> 1)), EC_TIMEOUTEEP);
|
||||
if (++dc >= 100)
|
||||
{
|
||||
dc = 0;
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eeprom_writealias(int slave, int alias, uint16 crc)
|
||||
{
|
||||
uint16 aiadr;
|
||||
uint8 eepctl;
|
||||
int ret;
|
||||
|
||||
if((ec_slavecount >= slave) && (slave > 0) && (alias <= 0xffff))
|
||||
{
|
||||
aiadr = 1 - slave;
|
||||
eepctl = 2;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* force Eeprom from PDI */
|
||||
eepctl = 0;
|
||||
ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* set Eeprom to master */
|
||||
|
||||
ret = ec_writeeepromAP(aiadr, 0x04 , alias, EC_TIMEOUTEEP);
|
||||
if (ret)
|
||||
ret = ec_writeeepromAP(aiadr, 0x07 , crc, EC_TIMEOUTEEP);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void eepromtool(char *ifname, int slave, int mode, char *fname)
|
||||
{
|
||||
int w, rc = 0, estart, esize;
|
||||
uint16 *wbuf;
|
||||
|
||||
/* initialise SOEM, bind socket to ifname */
|
||||
if (ec_init(ifname))
|
||||
{
|
||||
printf("ec_init on %s succeeded.\n",ifname);
|
||||
|
||||
w = 0x0000;
|
||||
wkc = ec_BRD(0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE); /* detect number of slaves */
|
||||
if (wkc > 0)
|
||||
{
|
||||
ec_slavecount = wkc;
|
||||
|
||||
printf("%d slaves found.\n",ec_slavecount);
|
||||
if((ec_slavecount >= slave) && (slave > 0))
|
||||
{
|
||||
if ((mode == MODE_INFO) || (mode == MODE_READBIN) || (mode == MODE_READINTEL))
|
||||
{
|
||||
tstart = osal_current_time();
|
||||
eeprom_read(slave, 0x0000, MINBUF); // read first 128 bytes
|
||||
|
||||
wbuf = (uint16 *)&ebuf[0];
|
||||
printf("Slave %d data\n", slave);
|
||||
printf(" PDI Control : %4.4X\n",*(wbuf + 0x00));
|
||||
printf(" PDI Config : %4.4X\n",*(wbuf + 0x01));
|
||||
printf(" Config Alias : %4.4X\n",*(wbuf + 0x04));
|
||||
printf(" Checksum : %4.4X\n",*(wbuf + 0x07));
|
||||
printf(" calculated : %4.4X\n",SIIcrc(&ebuf[0]));
|
||||
printf(" Vendor ID : %8.8X\n",*(uint32 *)(wbuf + 0x08));
|
||||
printf(" Product Code : %8.8X\n",*(uint32 *)(wbuf + 0x0A));
|
||||
printf(" Revision Number : %8.8X\n",*(uint32 *)(wbuf + 0x0C));
|
||||
printf(" Serial Number : %8.8X\n",*(uint32 *)(wbuf + 0x0E));
|
||||
printf(" Mailbox Protocol : %4.4X\n",*(wbuf + 0x1C));
|
||||
esize = (*(wbuf + 0x3E) + 1) * 128;
|
||||
if (esize > MAXBUF) esize = MAXBUF;
|
||||
printf(" Size : %4.4X = %d bytes\n",*(wbuf + 0x3E), esize);
|
||||
printf(" Version : %4.4X\n",*(wbuf + 0x3F));
|
||||
}
|
||||
if ((mode == MODE_READBIN) || (mode == MODE_READINTEL))
|
||||
{
|
||||
if (esize > MINBUF)
|
||||
eeprom_read(slave, MINBUF, esize - MINBUF); // read reminder
|
||||
|
||||
tend = osal_current_time();
|
||||
osal_time_diff(&tstart, &tend, &tdif);
|
||||
if (mode == MODE_READINTEL) output_intelhex(fname, esize);
|
||||
if (mode == MODE_READBIN) output_bin(fname, esize);
|
||||
|
||||
printf("\nTotal EEPROM read time :%ldms\n", (tdif.usec+(tdif.sec*1000000L)) / 1000);
|
||||
}
|
||||
if ((mode == MODE_WRITEBIN) || (mode == MODE_WRITEINTEL))
|
||||
{
|
||||
estart = 0;
|
||||
if (mode == MODE_WRITEINTEL) rc = input_intelhex(fname, &estart, &esize);
|
||||
if (mode == MODE_WRITEBIN) rc = input_bin(fname, &esize);
|
||||
|
||||
if (rc > 0)
|
||||
{
|
||||
wbuf = (uint16 *)&ebuf[0];
|
||||
printf("Slave %d\n", slave);
|
||||
printf(" Vendor ID : %8.8X\n",*(uint32 *)(wbuf + 0x08));
|
||||
printf(" Product Code : %8.8X\n",*(uint32 *)(wbuf + 0x0A));
|
||||
printf(" Revision Number : %8.8X\n",*(uint32 *)(wbuf + 0x0C));
|
||||
printf(" Serial Number : %8.8X\n",*(uint32 *)(wbuf + 0x0E));
|
||||
|
||||
printf("Busy");
|
||||
fflush(stdout);
|
||||
tstart = osal_current_time();
|
||||
eeprom_write(slave, estart, esize);
|
||||
tend = osal_current_time();
|
||||
osal_time_diff(&tstart, &tend, &tdif);
|
||||
|
||||
printf("\nTotal EEPROM write time :%ldms\n", (tdif.usec+(tdif.sec*1000000L)) / 1000);
|
||||
}
|
||||
else
|
||||
printf("Error reading file, abort.\n");
|
||||
}
|
||||
if (mode == MODE_WRITEALIAS)
|
||||
{
|
||||
if( eeprom_read(slave, 0x0000, CRCBUF) ) // read first 14 bytes
|
||||
{
|
||||
wbuf = (uint16 *)&ebuf[0];
|
||||
*(wbuf + 0x04) = alias;
|
||||
if(eeprom_writealias(slave, alias, SIIcrc(&ebuf[0])))
|
||||
{
|
||||
printf("Alias %4.4X written successfully to slave %d\n", alias, slave);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Alias not written\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Could not read slave EEPROM");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Slave number outside range.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("No slaves found!\n");
|
||||
}
|
||||
printf("End, close socket\n");
|
||||
/* stop SOEM, close socket */
|
||||
ec_close();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("No socket connection on %s\nExcecute as root\n",ifname);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("SOEM (Simple Open EtherCAT Master)\nEEPROM tool\n");
|
||||
|
||||
mode = MODE_NONE;
|
||||
if (argc > 3)
|
||||
{
|
||||
slave = atoi(argv[2]);
|
||||
if ((strncmp(argv[3], "-i", sizeof("-i")) == 0)) mode = MODE_INFO;
|
||||
if (argc > 4)
|
||||
{
|
||||
if ((strncmp(argv[3], "-r", sizeof("-r")) == 0)) mode = MODE_READBIN;
|
||||
if ((strncmp(argv[3], "-ri", sizeof("-ri")) == 0)) mode = MODE_READINTEL;
|
||||
if ((strncmp(argv[3], "-w", sizeof("-w")) == 0)) mode = MODE_WRITEBIN;
|
||||
if ((strncmp(argv[3], "-wi", sizeof("-wi")) == 0)) mode = MODE_WRITEINTEL;
|
||||
if ((strncmp(argv[3], "-walias", sizeof("-walias")) == 0))
|
||||
{
|
||||
mode = MODE_WRITEALIAS;
|
||||
alias = atoi(argv[4]);
|
||||
}
|
||||
}
|
||||
/* start tool */
|
||||
eepromtool(argv[1],slave,mode,argv[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec_adaptert * adapter = NULL;
|
||||
|
||||
printf("Usage: eepromtool ifname slave OPTION fname|alias\n");
|
||||
printf("ifname = eth0 for example\n");
|
||||
printf("slave = slave number in EtherCAT order 1..n\n");
|
||||
printf(" -i display EEPROM information\n");
|
||||
printf(" -walias write slave alias\n");
|
||||
printf(" -r read EEPROM, output binary format\n");
|
||||
printf(" -ri read EEPROM, output Intel Hex format\n");
|
||||
printf(" -w write EEPROM, input binary format\n");
|
||||
printf(" -wi write EEPROM, input Intel Hex format\n");
|
||||
|
||||
printf ("\nAvailable adapters:\n");
|
||||
adapter = ec_find_adapters ();
|
||||
while (adapter != NULL)
|
||||
{
|
||||
printf (" - %s (%s)\n", adapter->name, adapter->desc);
|
||||
adapter = adapter->next;
|
||||
}
|
||||
ec_free_adapters(adapter);
|
||||
}
|
||||
|
||||
printf("End program\n");
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
set(SOURCES red_test.c)
|
||||
add_executable(red_test ${SOURCES})
|
||||
target_link_libraries(red_test soem)
|
||||
install(TARGETS red_test DESTINATION bin)
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
set(SOURCES slaveinfo.c)
|
||||
add_executable(slaveinfo ${SOURCES})
|
||||
target_link_libraries(slaveinfo soem)
|
||||
install(TARGETS slaveinfo DESTINATION bin)
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
set(SOURCES tj30_test.c)
|
||||
add_executable(tj30_test ${SOURCES})
|
||||
target_link_libraries(tj30_test soem eceeprom_static)
|
||||
install(TARGETS tj30_test DESTINATION bin)
|
|
@ -0,0 +1,224 @@
|
|||
#ifndef __LOGN_H___
|
||||
#define __LOGN_H___
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef RT_VERSION_MAJOR
|
||||
#define LOGN_PRINTF(...) rt_kprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOGN_PRINTF(...) printf(__VA_ARGS__)
|
||||
#endif // RT_VERSION_MAJOR
|
||||
|
||||
#if defined(RT_USING_ULOG)
|
||||
#include <ulog.h>
|
||||
#else
|
||||
#define LOG_LVL_ERROR 0
|
||||
#define LOG_LVL_WARNING 1
|
||||
#define LOG_LVL_INFO 2
|
||||
#define LOG_LVL_DBG 3
|
||||
|
||||
#ifdef LOG_TAG
|
||||
#undef DBG_TAG
|
||||
#define DBG_TAG LOG_TAG
|
||||
#else
|
||||
#define LOG_TAG DGB_TAG
|
||||
#endif // LOG_TAG
|
||||
|
||||
#ifdef RT_DEBUG
|
||||
|
||||
#ifdef LOG_LVL
|
||||
#undef DBG_LVL
|
||||
#define DBG_LVL LOG_LVL
|
||||
#else
|
||||
#define LOG_LVL DBG_LVL
|
||||
#endif // LOG_LVL
|
||||
|
||||
#include <rtdbg.h>
|
||||
#else
|
||||
#define LOGN_ENABLE
|
||||
#endif // RT_DEBUG
|
||||
#endif // !RT_USING_ULOG
|
||||
|
||||
#if (LOG_LVL < LOG_LVL_DBG)
|
||||
#define LOG0(fmt, ...)
|
||||
#define LOG1(fmt, ...)
|
||||
#define LOG2(fmt, ...)
|
||||
#define LOG3(fmt, ...)
|
||||
#define LOG4(fmt, ...)
|
||||
#define LOG5(fmt, ...)
|
||||
#define LOG6(fmt, ...)
|
||||
#define LOG7(fmt, ...)
|
||||
#define LOG10(fmt, ...)
|
||||
#define LOG11(fmt, ...)
|
||||
#define LOG12(fmt, ...)
|
||||
#define LOG13(fmt, ...)
|
||||
#define LOG14(fmt, ...)
|
||||
#define LOG15(fmt, ...)
|
||||
#define LOG16(fmt, ...)
|
||||
#define LOG17(fmt, ...)
|
||||
#else
|
||||
|
||||
/**
|
||||
* CSI(Control Sequence Introducer/Initiator) sign
|
||||
* more information on https://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
*/
|
||||
#define CSI_START "\033["
|
||||
#define CSI_END "\033[0m"
|
||||
/* output log front color */
|
||||
#define F_BLACK "30m"
|
||||
#define F_RED "31m"
|
||||
#define F_GREEN "32m"
|
||||
#define F_YELLOW "33m"
|
||||
#define F_BLUE "34m"
|
||||
#define F_MAGENTA "35m"
|
||||
#define F_CYAN "36m"
|
||||
#define F_WHITE "37m"
|
||||
/* output log backgroup color */
|
||||
#define B_BLACK "40m"
|
||||
#define B_RED "41m"
|
||||
#define B_GREEN "42m"
|
||||
#define B_YELLOW "43m"
|
||||
#define B_BLUE "44m"
|
||||
#define B_MAGENTA "45m"
|
||||
#define B_CYAN "46m"
|
||||
#define B_WHITE "47m"
|
||||
// 亮前景色
|
||||
#define F_GRAY "90m"
|
||||
#define F_B_BLACK "90m"
|
||||
#define F_B_RED "91m"
|
||||
#define F_B_GREEN "92m"
|
||||
#define F_B_YELLOW "93m"
|
||||
#define F_B_BLUE "94m"
|
||||
#define F_B_MAGENTA "95m"
|
||||
#define F_B_CYAN "96m"
|
||||
#define F_B_WHITE "97m"
|
||||
// 亮背景色
|
||||
#define B_GRAY "100m"
|
||||
#define B_B_BLACK "100m"
|
||||
#define B_B_RED "101m"
|
||||
#define B_B_GREEN "102m"
|
||||
#define B_B_YELLOW "103m"
|
||||
#define B_B_BLUE "104m"
|
||||
#define B_B_MAGENTA "105m"
|
||||
#define B_B_CYAN "106m"
|
||||
#define B_B_WHITE "107m"
|
||||
|
||||
#define SET_COLOR(c, s) CSI_START c s CSI_END
|
||||
#ifdef RT_USING_ULOG
|
||||
#define logn_line(color_n, fmt, ...) ulog_d(LOG_TAG, SET_COLOR(color_n, fmt), ##__VA_ARGS__)
|
||||
#else // !RT_USING_ULOG
|
||||
|
||||
#if (DBG_LEVEL >= DBG_LOG || defined(LOGN_ENABLE))
|
||||
|
||||
#ifndef RT_DEBUG
|
||||
#define dbg_log_line(lvl, color_n, fmt, ...) LOGN_PRINTF(LOG_TAG ":" SET_COLOR(color_n, fmt) "\n", ##__VA_ARGS__)
|
||||
#endif // !RT_DEBUG
|
||||
|
||||
#define logn(color_n, fmt, ...) LOGN_PRINTF(SET_COLOR(color_n, fmt), ##__VA_ARGS__)
|
||||
#define logn_line(color_n, fmt, ...) LOGN_PRINTF(SET_COLOR(color_n, fmt) "\n", ##__VA_ARGS__)
|
||||
#define logn_lvl(color_n, fmt, ...) dbg_log_line(LOG_LVL, color_n, fmt, ##__VA_ARGS__)
|
||||
|
||||
#else // !(DBG_LEVEL >= DBG_LOG)
|
||||
#define logn_line(...)
|
||||
#endif // (DBG_LEVEL >= DBG_LOG)
|
||||
|
||||
#endif // RT_USING_ULOG
|
||||
|
||||
#ifdef USE_LOG0
|
||||
#define LOG0(fmt, ...) logn_lvl("30;100m", fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG0(fmt, ...)
|
||||
#endif // USE_LOG0
|
||||
#ifdef USE_LOG1
|
||||
#define LOG1(fmt, ...) logn_lvl(F_RED, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG1(fmt, ...)
|
||||
#endif // USE_LOG1
|
||||
#ifdef USE_LOG2
|
||||
#define LOG2(fmt, ...) logn_lvl(F_GREEN, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG2(fmt, ...)
|
||||
#endif // USE_LOG2
|
||||
#ifdef USE_LOG3
|
||||
#define LOG3(fmt, ...) logn_lvl(F_YELLOW, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG3(fmt, ...)
|
||||
#endif // USE_LOG3
|
||||
#ifdef USE_LOG4
|
||||
#define LOG4(fmt, ...) logn_lvl(F_BLUE, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG4(fmt, ...)
|
||||
#endif // USE_LOG4
|
||||
#ifdef USE_LOG5
|
||||
#define LOG5(fmt, ...) logn_lvl(F_MAGENTA, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG5(fmt, ...)
|
||||
#endif // USE_LOG5
|
||||
#ifdef USE_LOG6
|
||||
#define LOG6(fmt, ...) logn_lvl(F_CYAN, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG6(fmt, ...)
|
||||
#endif // USE_LOG6
|
||||
#ifdef USE_LOG7
|
||||
#define LOG7(fmt, ...) logn_lvl(F_WHITE, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG7(fmt, ...)
|
||||
#endif // USE_LOG7
|
||||
|
||||
#ifdef USE_LOG10
|
||||
#define LOG10(fmt, ...) logn_lvl(F_GRAY, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG10(fmt, ...)
|
||||
#endif // USE_LOG10
|
||||
#ifdef USE_LOG11
|
||||
#define LOG11(fmt, ...) logn_lvl(F_B_RED, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG11(fmt, ...)
|
||||
#endif // USE_LOG11
|
||||
#ifdef USE_LOG12
|
||||
#define LOG12(fmt, ...) logn_lvl(F_B_GREEN, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG12(fmt, ...)
|
||||
#endif // USE_LOG12
|
||||
#ifdef USE_LOG13
|
||||
#define LOG13(fmt, ...) logn_lvl(F_B_YELLOW, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG13(fmt, ...)
|
||||
#endif // USE_LOG13
|
||||
#ifdef USE_LOG14
|
||||
#define LOG14(fmt, ...) logn_lvl(F_B_BLUE, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG14(fmt, ...)
|
||||
#endif // USE_LOG14
|
||||
#ifdef USE_LOG15
|
||||
#define LOG15(fmt, ...) logn_lvl(F_B_MAGENTA, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG15(fmt, ...)
|
||||
#endif // USE_LOG15
|
||||
#ifdef USE_LOG16
|
||||
#define LOG16(fmt, ...) logn_lvl(F_B_CYAN, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG16(fmt, ...)
|
||||
#endif // USE_LOG16
|
||||
#ifdef USE_LOG17
|
||||
#define LOG17(fmt, ...) logn_lvl(F_B_WHITE, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG17(fmt, ...)
|
||||
#endif // USE_LOG17
|
||||
|
||||
#ifndef USE_LOG_D
|
||||
#undef LOG_D
|
||||
#define LOG_D(...)
|
||||
#endif // USE_LOG_D
|
||||
#endif
|
||||
|
||||
#define IS_USE_LOGN(n) ((defined(USE_LOG##n)) && (LOG_LVL >= LOG_LVL_DBG))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !__LOGN_H___
|
|
@ -0,0 +1,853 @@
|
|||
/** \file
|
||||
* \brief Example code for Simple Open EtherCAT master
|
||||
*
|
||||
* Usage : red_test [ifname1] [ifname2] [cycletime]
|
||||
* ifname is NIC interface, f.e. eth0
|
||||
* cycletime in us, f.e. 500
|
||||
*
|
||||
* This is a redundancy test.
|
||||
*
|
||||
* (c)Arthur Ketels 2008
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "eceeprom.h"
|
||||
#include "ethercat.h"
|
||||
#include "osal.h"
|
||||
|
||||
#define LOG_TAG "io_test"
|
||||
#define LOG_LVL LOG_LVL_DBG
|
||||
// #define LOG_LVL LOG_LVL_INFO
|
||||
|
||||
// #define USE_LOG1
|
||||
// #define USE_LOG2
|
||||
// #define USE_LOG3
|
||||
// #define USE_LOG4
|
||||
// #define USE_LOG5
|
||||
// #define USE_LOG6
|
||||
// #define USE_LOG_D
|
||||
#include "logn.h"
|
||||
|
||||
#define NSEC_PER_SEC 1000000000
|
||||
#define EC_TIMEOUTMON 500
|
||||
#define TEST_STEP_CYCLETIME (75 * 1000) // us
|
||||
#define INPUT_CHECK_TIMEOUT (5 * 1000) // us
|
||||
#define MAX_SLAVE 8
|
||||
|
||||
#define ROL_U16(a, n) ((uint16_t)((a) << (n) | (a) >> (16 - n)))
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
#define GET_BIT(value, bit) (((value) >> (bit)) & 1) // 读取指定位
|
||||
#define CPL_BIT(value, bit) ((value) ^= (1 << (bit))) // 取反指定位
|
||||
#define CLR_BIT(value, bit) ((value) &= ~(1 << (bit))) // 把某个位置0
|
||||
#define SET_BIT(value, bit) ((value) |= (1 << (bit))) // 把某个位置1
|
||||
|
||||
#define show_err(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
/* 擦除行, 输出 */ \
|
||||
sprintf(ec_error.str + strlen(ec_error.str), CSI_START "2K" fmt, ##__VA_ARGS__); \
|
||||
ec_error.cnt++; \
|
||||
ec_error.is_showed = false; \
|
||||
} while (0)
|
||||
|
||||
#define time_cmp(a, b, CMP) \
|
||||
(((a)->sec == (b)->sec) ? ((a)->usec CMP(b)->usec) : ((a)->sec CMP(b)->sec))
|
||||
|
||||
#define set_check_stop_time(current_time, us, stop_time) \
|
||||
do \
|
||||
{ \
|
||||
(stop_time)->sec = (current_time)->sec + (us) / 1000000; \
|
||||
(stop_time)->usec = (current_time)->usec + (us) % 1000000; \
|
||||
if ((stop_time)->usec >= 1000000) \
|
||||
{ \
|
||||
++(stop_time)->sec; \
|
||||
(stop_time)->usec -= 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct sched_param schedp;
|
||||
char IOmap[4096];
|
||||
pthread_t thread1, thread2;
|
||||
struct timeval tv, t1, t2;
|
||||
int32_t dorun = 0;
|
||||
int32_t test_step = 0;
|
||||
int32_t test_cycle = 0;
|
||||
int deltat, tmax = 0;
|
||||
int64 toff, gl_delta;
|
||||
int DCdiff;
|
||||
int os;
|
||||
uint8 ob;
|
||||
uint16 ob2;
|
||||
uint8 *digout = 0;
|
||||
int expectedWKC;
|
||||
volatile int wkc;
|
||||
boolean inOP;
|
||||
uint8 currentgroup = 0;
|
||||
static int cycletime;
|
||||
static int step_time;
|
||||
|
||||
static struct
|
||||
{
|
||||
char str[1024];
|
||||
size_t cnt;
|
||||
bool is_showed;
|
||||
} ec_error;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ssize_t input_bytes;
|
||||
ssize_t output_bytes;
|
||||
uint8_t outputs[4];
|
||||
uint8_t inputs[4];
|
||||
uint8_t is_out_changed[4];
|
||||
uint8_t is_in_changed[4];
|
||||
ec_timet check_stop_time[32];
|
||||
ec_timet output_change_time[32];
|
||||
ec_timet in_out_time_diff[32];
|
||||
ec_timet max_in_out_time_diff[32];
|
||||
|
||||
bool error[32];
|
||||
size_t err_cnt[32];
|
||||
} io_test_t;
|
||||
|
||||
io_test_t io_test[MAX_SLAVE + 1] = {0};
|
||||
|
||||
static uint16_t test_list[] = {
|
||||
ROL_U16(0x4241u, 0),
|
||||
ROL_U16(0x4241u, 1),
|
||||
ROL_U16(0x4241u, 2),
|
||||
ROL_U16(0x4241u, 3),
|
||||
ROL_U16(0x4241u, 4),
|
||||
ROL_U16(0x4241u, 5),
|
||||
ROL_U16(0x4241u, 6),
|
||||
ROL_U16(0x4241u, 7),
|
||||
ROL_U16(0x4241u, 8),
|
||||
ROL_U16(0x4241u, 9),
|
||||
ROL_U16(0x4241u, 10),
|
||||
ROL_U16(0x4241u, 11),
|
||||
ROL_U16(0x4241u, 12),
|
||||
ROL_U16(0x4241u, 13),
|
||||
ROL_U16(0x4241u, 14),
|
||||
ROL_U16(0x4241u, 15),
|
||||
ROL_U16(0x4241u, 0),
|
||||
ROL_U16(0x4241u, 1),
|
||||
ROL_U16(0x4241u, 2),
|
||||
ROL_U16(0x4241u, 3),
|
||||
ROL_U16(0x4241u, 4),
|
||||
ROL_U16(0x4241u, 5),
|
||||
ROL_U16(0x4241u, 6),
|
||||
ROL_U16(0x4241u, 7),
|
||||
ROL_U16(0x4241u, 8),
|
||||
ROL_U16(0x4241u, 9),
|
||||
ROL_U16(0x4241u, 10),
|
||||
ROL_U16(0x4241u, 11),
|
||||
ROL_U16(0x4241u, 12),
|
||||
ROL_U16(0x4241u, 13),
|
||||
ROL_U16(0x4241u, 14),
|
||||
ROL_U16(0x4241u, 15),
|
||||
ROL_U16(0x4241u, 0),
|
||||
ROL_U16(0x4241u, 1),
|
||||
ROL_U16(0x4241u, 2),
|
||||
ROL_U16(0x4241u, 3),
|
||||
ROL_U16(0x4241u, 4),
|
||||
ROL_U16(0x4241u, 5),
|
||||
ROL_U16(0x4241u, 6),
|
||||
ROL_U16(0x4241u, 7),
|
||||
ROL_U16(0x4241u, 8),
|
||||
ROL_U16(0x4241u, 9),
|
||||
ROL_U16(0x4241u, 10),
|
||||
ROL_U16(0x4241u, 11),
|
||||
ROL_U16(0x4241u, 12),
|
||||
ROL_U16(0x4241u, 13),
|
||||
ROL_U16(0x4241u, 14),
|
||||
ROL_U16(0x4241u, 15),
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0xFFFFu,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
static int sprint_ms(char *buff, ec_timet *t)
|
||||
{
|
||||
int n;
|
||||
if ((t)->sec) // >= 1000ms
|
||||
{
|
||||
n = sprintf(buff, "%u%03u", (t)->sec, (t)->usec / 1000);
|
||||
}
|
||||
else if ((t)->usec < 10 * 1000) // 0.00 ~ 9.99ms
|
||||
{
|
||||
n = sprintf(buff, "%u.%02u", (t)->usec / 1000, (t)->usec / 10 % 100);
|
||||
}
|
||||
else if ((t)->usec < 100 * 1000) // 10.0 ~ 99.9ms
|
||||
{
|
||||
n = sprintf(buff, "%u.%u", (t)->usec / 1000, (t)->usec / 100 % 10);
|
||||
}
|
||||
else // 100 ~ 999ms
|
||||
{
|
||||
n = sprintf(buff, " %u", (t)->usec / 1000);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void show_check(void)
|
||||
{
|
||||
struct termios orig_termios;
|
||||
tcgetattr(STDIN_FILENO, &orig_termios);
|
||||
|
||||
struct termios new_termios = orig_termios;
|
||||
new_termios.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
|
||||
|
||||
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
char ch;
|
||||
bool is_first = true;
|
||||
ec_error.is_showed = true;
|
||||
printf(CSI_START "?25l"); // 隐藏光标
|
||||
for (;;)
|
||||
{
|
||||
// 按空格,q, x 键退出
|
||||
int result = read(STDIN_FILENO, &ch, 1);
|
||||
if (result == 1 && (ch == ' ' || ch == 'q' || ch == 'x'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (is_first)
|
||||
{
|
||||
is_first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(CSI_START "4F"); // 光标上移4行,到行首
|
||||
for (int i = 1; i <= ec_slavecount; i++)
|
||||
{
|
||||
printf(CSI_START "5F"); // 光标上移5行,到行首
|
||||
}
|
||||
}
|
||||
if (!ec_error.is_showed)
|
||||
{
|
||||
printf("%s", ec_error.str); // 输出
|
||||
ec_error.str[0] = '\0';
|
||||
ec_error.is_showed = true;
|
||||
}
|
||||
printf("ID | Type | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | "
|
||||
"15 | 16 |\n"
|
||||
"---+-------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-"
|
||||
"---+----+\n");
|
||||
for (int i = 1; i <= ec_slavecount; i++)
|
||||
{
|
||||
char buff[64 * 1024];
|
||||
char *p = buff;
|
||||
// show output / input
|
||||
p += sprintf(p, "%2d | Out/In|", i);
|
||||
int j = 0;
|
||||
for (; j < io_test[i].output_bytes; j++)
|
||||
{
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
bool b = GET_BIT(io_test[i].outputs[j], k);
|
||||
if (b)
|
||||
{
|
||||
p += sprintf(p, SET_COLOR(B_RED, " 1"));
|
||||
}
|
||||
else
|
||||
{
|
||||
p += sprintf(p, " 0");
|
||||
}
|
||||
b = GET_BIT(io_test[i].inputs[j], k);
|
||||
if (b)
|
||||
{
|
||||
p += sprintf(p, SET_COLOR(B_BLUE, "/1"));
|
||||
}
|
||||
else
|
||||
{
|
||||
p += sprintf(p, "/0");
|
||||
}
|
||||
p += sprintf(p, "|");
|
||||
}
|
||||
}
|
||||
for (; j < 2; j++)
|
||||
{
|
||||
p += sprintf(p, " | | | | | | | |");
|
||||
}
|
||||
// show diff
|
||||
p += sprintf(p, "\n |Diff/ms|");
|
||||
j = 0;
|
||||
for (; j < io_test[i].input_bytes; j++)
|
||||
{
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
int idx = j * 8 + k;
|
||||
if (io_test[i].max_in_out_time_diff[idx].sec > 0)
|
||||
{
|
||||
p += sprintf(p, SET_COLOR(B_RED, " !! "));
|
||||
}
|
||||
else
|
||||
{
|
||||
p += sprint_ms(p, &io_test[i].in_out_time_diff[idx]);
|
||||
}
|
||||
p += sprintf(p, "|");
|
||||
}
|
||||
}
|
||||
for (; j < 2; j++)
|
||||
{
|
||||
p += sprintf(p, " | | | | | | | |");
|
||||
}
|
||||
// show max
|
||||
p += sprintf(p, "\n | Max/ms|");
|
||||
j = 0;
|
||||
for (; j < io_test[i].input_bytes; j++)
|
||||
{
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
int idx = j * 8 + k;
|
||||
if (io_test[i].error[j * 8 + k]) // 出错
|
||||
{
|
||||
if (io_test[i].max_in_out_time_diff[idx].sec > 9)
|
||||
{
|
||||
p += sprintf(p, SET_COLOR(B_RED, " !! "));
|
||||
}
|
||||
else
|
||||
{
|
||||
char ms[16];
|
||||
sprint_ms(ms, &io_test[i].max_in_out_time_diff[idx]);
|
||||
p += sprintf(p, SET_COLOR(B_RED, "%s"), ms);
|
||||
}
|
||||
}
|
||||
else // 正常
|
||||
{
|
||||
if (io_test[i].max_in_out_time_diff[idx].sec > 0)
|
||||
{
|
||||
p += sprintf(p, SET_COLOR(B_GREEN, " !! "));
|
||||
}
|
||||
else
|
||||
{
|
||||
char ms[16];
|
||||
sprint_ms(ms, &io_test[i].max_in_out_time_diff[idx]);
|
||||
p += sprintf(p, SET_COLOR(B_GREEN, "%s"), ms);
|
||||
}
|
||||
}
|
||||
p += sprintf(p, "|");
|
||||
}
|
||||
}
|
||||
for (; j < 2; j++)
|
||||
{
|
||||
p += sprintf(p, " | | | | | | | |");
|
||||
}
|
||||
// err_cnt
|
||||
p += sprintf(p, "\n |ErrCnt |");
|
||||
j = 0;
|
||||
for (; j < io_test[i].input_bytes; j++)
|
||||
{
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
int idx = j * 8 + k;
|
||||
if (io_test[i].err_cnt[idx] == 0)
|
||||
{
|
||||
p += sprintf(p, " 0");
|
||||
}
|
||||
else if (io_test[i].err_cnt[idx] > 999)
|
||||
{
|
||||
p += sprintf(p, SET_COLOR(B_B_RED, "999+"));
|
||||
}
|
||||
else
|
||||
{
|
||||
p += sprintf(p, SET_COLOR(B_B_RED, " %3lu"), io_test[i].err_cnt[idx]);
|
||||
}
|
||||
p += sprintf(p, "|");
|
||||
}
|
||||
}
|
||||
for (; j < 2; j++)
|
||||
{
|
||||
p += sprintf(p, " | | | | | | | |");
|
||||
}
|
||||
|
||||
p += sprintf(p, "\n---+-------+----+----+----+----+----+----+----+----+----+----+----+-"
|
||||
"---+----+----+----+----+\n");
|
||||
printf("%s", buff);
|
||||
}
|
||||
printf("Processdata cycle %5d, cycletime %dus, Wck %3d, DCtime %12" PRId64
|
||||
"ns, dt " CSI_START "K" /*擦除到行尾*/ "%6" PRId64 "ns\n",
|
||||
dorun, cycletime, wkc, ec_DCtime, gl_delta);
|
||||
printf("Test cycle %d, Step time %dms, Test step %3d, EC Error count %lu."
|
||||
" Press key SPACE or 'q' or 'x' to EXIT.\n",
|
||||
test_cycle, step_time / 1000, test_step, ec_error.cnt);
|
||||
|
||||
fflush(stdout);
|
||||
osal_usleep(50000);
|
||||
}
|
||||
printf(CSI_START "?25h"); // 显示光标
|
||||
}
|
||||
|
||||
void tj30_test(char *ifname)
|
||||
{
|
||||
int cnt, i;
|
||||
|
||||
printf("Starting TJ30-XXXX test\n");
|
||||
|
||||
/* initialise SOEM, bind socket to ifname */
|
||||
if (!ec_init(ifname))
|
||||
{
|
||||
printf("No socket connection on %s\nExcecute as root\n", ifname);
|
||||
return;
|
||||
}
|
||||
printf("ec_init on %s succeeded.\n", ifname);
|
||||
/* find and auto-config slaves */
|
||||
if (ec_config(FALSE, &IOmap) <= 0)
|
||||
{
|
||||
printf("No slaves found!\n");
|
||||
goto __exit;
|
||||
}
|
||||
printf("%d slaves found and configured.\n", ec_slavecount);
|
||||
/* check for TJ30-1616DN */
|
||||
for (cnt = 1; cnt <= ec_slavecount; cnt++)
|
||||
{
|
||||
if (ec_slave[cnt].eep_id != 0x00010200)
|
||||
{
|
||||
printf("Slave %i: ID (%u) 不匹配!\n", cnt, ec_slave[cnt].eep_id);
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
/* wait for all slaves to reach SAFE_OP state */
|
||||
ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE);
|
||||
|
||||
/* configure DC options for every DC capable slave found in the list */
|
||||
ec_configdc();
|
||||
|
||||
/* read indevidual slave state and store in ec_slave[] */
|
||||
ec_readstate();
|
||||
for (cnt = 1; cnt <= ec_slavecount; cnt++)
|
||||
{
|
||||
int32_t sn = ecEepromGetSN(cnt);
|
||||
logn(F_B_BLUE,
|
||||
"Slave:%d Name:%s ID: " CSI_START B_B_WHITE "%u/0x%08x" CSI_END CSI_START F_B_BLUE
|
||||
" SN:" CSI_START B_B_WHITE "%d" CSI_END CSI_START F_B_BLUE
|
||||
" Output size:%3dbits Input size:%3dbits\n",
|
||||
cnt, ec_slave[cnt].name, ec_slave[cnt].eep_id, ec_slave[cnt].eep_id, sn,
|
||||
ec_slave[cnt].Obits, ec_slave[cnt].Ibits);
|
||||
logn(F_B_BLUE, "State:%2d delay:%3d DC:%2d Out:%p,%4d In:%p,%4d\n", ec_slave[cnt].state,
|
||||
(int)ec_slave[cnt].pdelay, ec_slave[cnt].hasdc, ec_slave[cnt].outputs,
|
||||
ec_slave[cnt].Obytes, ec_slave[cnt].inputs, ec_slave[cnt].Ibytes);
|
||||
|
||||
io_test[cnt].input_bytes = ec_slave[cnt].Ibytes;
|
||||
if (io_test[cnt].input_bytes == 0 && ec_slave[cnt].Ibits > 0)
|
||||
{
|
||||
io_test[cnt].input_bytes = 1;
|
||||
}
|
||||
io_test[cnt].output_bytes = ec_slave[cnt].Obytes;
|
||||
if (io_test[cnt].output_bytes == 0 && ec_slave[cnt].Obits > 0)
|
||||
{
|
||||
io_test[cnt].output_bytes = 1;
|
||||
}
|
||||
}
|
||||
expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
|
||||
printf("Calculated workcounter %d\n", expectedWKC);
|
||||
|
||||
printf("Request operational state for all slaves\n");
|
||||
ec_slave[0].state = EC_STATE_OPERATIONAL;
|
||||
/* request OP state for all slaves */
|
||||
ec_writestate(0);
|
||||
/* wait for all slaves to reach OP state */
|
||||
ec_statecheck(0, EC_STATE_OPERATIONAL, 5 * EC_TIMEOUTSTATE);
|
||||
/* activate cyclic process data */
|
||||
dorun = 1;
|
||||
/* 运行模式 */
|
||||
if (ec_slave[0].state == EC_STATE_OPERATIONAL)
|
||||
{
|
||||
printf("Operational state reached for all slaves.\n");
|
||||
inOP = TRUE;
|
||||
show_check();
|
||||
printf("Test is END.\n");
|
||||
dorun = 0;
|
||||
inOP = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Not all slaves reached operational state.\n");
|
||||
ec_readstate();
|
||||
for (i = 1; i <= ec_slavecount; i++)
|
||||
{
|
||||
if (ec_slave[i].state != EC_STATE_OPERATIONAL)
|
||||
{
|
||||
printf("Slave %d State=0x%2.2x StatusCode=0x%4.4x : %s\n", i, ec_slave[i].state,
|
||||
ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Request safe operational state for all slaves\n");
|
||||
ec_slave[0].state = EC_STATE_SAFE_OP;
|
||||
/* request SAFE_OP state for all slaves */
|
||||
ec_writestate(0);
|
||||
|
||||
__exit:
|
||||
printf("End IO test, close socket\n");
|
||||
/* stop SOEM, close socket */
|
||||
ec_close();
|
||||
}
|
||||
|
||||
/* add ns to timespec */
|
||||
void add_timespec(struct timespec *ts, int64 addtime)
|
||||
{
|
||||
int64 sec, nsec;
|
||||
|
||||
nsec = addtime % NSEC_PER_SEC;
|
||||
sec = (addtime - nsec) / NSEC_PER_SEC;
|
||||
ts->tv_sec += sec;
|
||||
ts->tv_nsec += nsec;
|
||||
if (ts->tv_nsec >= NSEC_PER_SEC)
|
||||
{
|
||||
nsec = ts->tv_nsec % NSEC_PER_SEC;
|
||||
ts->tv_sec += (ts->tv_nsec - nsec) / NSEC_PER_SEC;
|
||||
ts->tv_nsec = nsec;
|
||||
}
|
||||
}
|
||||
|
||||
/* PI calculation to get linux time synced to DC time */
|
||||
void ec_sync(int64 reftime, int64 cycletime, int64 *offsettime)
|
||||
{
|
||||
static int64 integral = 0;
|
||||
int64 delta;
|
||||
/* set linux sync point 50us later than DC sync, just as example */
|
||||
delta = (reftime - 50000) % cycletime;
|
||||
if (delta > (cycletime / 2))
|
||||
{
|
||||
delta = delta - cycletime;
|
||||
}
|
||||
if (delta > 0)
|
||||
{
|
||||
integral++;
|
||||
}
|
||||
if (delta < 0)
|
||||
{
|
||||
integral--;
|
||||
}
|
||||
*offsettime = -(delta / 100) - (integral / 20);
|
||||
gl_delta = delta;
|
||||
}
|
||||
|
||||
static void check_io()
|
||||
{
|
||||
ec_timet current_time = osal_current_time();
|
||||
for (int i = 1; i <= ec_slavecount; i++)
|
||||
{
|
||||
for (int j = 0; j < io_test[i].input_bytes; j++)
|
||||
{
|
||||
uint8_t is_in_changed = io_test[i].inputs[j] ^ ec_slave[i].inputs[j];
|
||||
io_test[i].is_in_changed[j] |= is_in_changed;
|
||||
io_test[i].inputs[j] = ec_slave[i].inputs[j];
|
||||
uint8_t is_not_same = io_test[i].inputs[j] ^ io_test[i].outputs[j];
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
// if (!GET_BIT(io_test[i].is_out_changed[j], k)) //输出未变
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
int idx = j * 8 + k;
|
||||
if (GET_BIT(is_not_same, k)) // update result
|
||||
{
|
||||
if (GET_BIT(io_test[i].is_out_changed[j], k))
|
||||
{
|
||||
if (time_cmp(&io_test[i].check_stop_time[idx], ¤t_time, <)) // 到期
|
||||
{
|
||||
io_test[i].error[idx] = true;
|
||||
io_test[i].err_cnt[idx]++;
|
||||
CLR_BIT(io_test[i].is_out_changed[j], k);
|
||||
CLR_BIT(io_test[i].is_in_changed[j], k);
|
||||
if (time_cmp(&io_test[i].in_out_time_diff[idx],
|
||||
&io_test[i].max_in_out_time_diff[idx], >))
|
||||
{
|
||||
io_test[i].max_in_out_time_diff[idx]
|
||||
= io_test[i].in_out_time_diff[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
else // 输出未变,且不同,就出错
|
||||
{
|
||||
if (GET_BIT(io_test[i].is_in_changed[j], k))
|
||||
{
|
||||
io_test[i].max_in_out_time_diff[idx].sec = 0;
|
||||
io_test[i].max_in_out_time_diff[idx].usec = 99900;
|
||||
CLR_BIT(io_test[i].is_in_changed[j], k);
|
||||
io_test[i].error[idx] = true;
|
||||
io_test[i].err_cnt[idx]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (GET_BIT(io_test[i].is_out_changed[j], k)) // 相同, 且输出有变化
|
||||
{
|
||||
if (GET_BIT(io_test[i].is_in_changed[j], k)) // update time diff
|
||||
{
|
||||
CLR_BIT(io_test[i].is_in_changed[j], k);
|
||||
CLR_BIT(io_test[i].is_out_changed[j], k);
|
||||
osal_time_diff(&io_test[i].output_change_time[idx], ¤t_time,
|
||||
&io_test[i].in_out_time_diff[idx]);
|
||||
if (time_cmp(&io_test[i].in_out_time_diff[idx],
|
||||
&io_test[i].max_in_out_time_diff[idx], >))
|
||||
{
|
||||
io_test[i].max_in_out_time_diff[idx] = io_test[i].in_out_time_diff[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_output(void)
|
||||
{
|
||||
static osal_timert tmr = {0};
|
||||
static size_t list_idx = 0;
|
||||
|
||||
if (osal_timer_is_expired(&tmr))
|
||||
{
|
||||
test_step++;
|
||||
osal_timer_start(&tmr, step_time);
|
||||
|
||||
uint16_t test_val = test_list[list_idx];
|
||||
list_idx++;
|
||||
if (list_idx >= ARRAY_SIZE(test_list))
|
||||
{
|
||||
list_idx = 0;
|
||||
test_cycle++;
|
||||
}
|
||||
|
||||
ec_timet current_time = osal_current_time();
|
||||
for (int i = 1; i <= ec_slavecount; i++)
|
||||
{
|
||||
for (int j = 0; j < io_test[i].output_bytes; j++)
|
||||
{
|
||||
ec_slave[i].outputs[j] = (uint8_t)((test_val >> (j % 2)) & 0xff);
|
||||
uint8_t is_out_changed = io_test[i].outputs[j] ^ ec_slave[i].outputs[j];
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
size_t p_idx = j * 8 + k;
|
||||
if (GET_BIT(is_out_changed, k))
|
||||
{
|
||||
io_test[i].output_change_time[p_idx] = current_time;
|
||||
set_check_stop_time(¤t_time, INPUT_CHECK_TIMEOUT,
|
||||
&io_test[i].check_stop_time[p_idx]);
|
||||
}
|
||||
}
|
||||
io_test[i].is_out_changed[j] |= is_out_changed;
|
||||
io_test[i].outputs[j] = ec_slave[i].outputs[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RT EtherCAT thread */
|
||||
OSAL_THREAD_FUNC_RT ecatthread(void *ptr)
|
||||
{
|
||||
struct timespec ts, tleft;
|
||||
int ht;
|
||||
|
||||
int64 cycletime;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
ht = (ts.tv_nsec / 1000000) + 1; /* round to nearest ms */
|
||||
ts.tv_nsec = ht * 1000000;
|
||||
if (ts.tv_nsec >= NSEC_PER_SEC)
|
||||
{
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= NSEC_PER_SEC;
|
||||
}
|
||||
cycletime = *(int *)ptr * 1000; /* cycletime in ns */
|
||||
toff = 0;
|
||||
dorun = 0;
|
||||
ec_send_processdata();
|
||||
while (1)
|
||||
{
|
||||
/* calculate next cycle start */
|
||||
add_timespec(&ts, cycletime + toff);
|
||||
/* wait to cycle start */
|
||||
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, &tleft);
|
||||
if (dorun == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (dorun < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
dorun++;
|
||||
wkc = ec_receive_processdata(EC_TIMEOUTRET);
|
||||
check_io();
|
||||
|
||||
write_output();
|
||||
if (ec_slave[0].hasdc)
|
||||
{
|
||||
/* calulate toff to get linux time and DC synced */
|
||||
ec_sync(ec_DCtime, cycletime, &toff);
|
||||
}
|
||||
ec_send_processdata();
|
||||
}
|
||||
}
|
||||
|
||||
OSAL_THREAD_FUNC ecatcheck(void *ptr)
|
||||
{
|
||||
int slave;
|
||||
|
||||
(void)ptr;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (inOP && ((wkc < expectedWKC) || ec_group[currentgroup].docheckstate))
|
||||
{
|
||||
/* one ore more slaves are not responding */
|
||||
ec_group[currentgroup].docheckstate = FALSE;
|
||||
ec_readstate();
|
||||
for (slave = 1; slave <= ec_slavecount; slave++)
|
||||
{
|
||||
if ((ec_slave[slave].group == currentgroup)
|
||||
&& (ec_slave[slave].state != EC_STATE_OPERATIONAL))
|
||||
{
|
||||
ec_group[currentgroup].docheckstate = TRUE;
|
||||
if (ec_slave[slave].state == (EC_STATE_SAFE_OP + EC_STATE_ERROR))
|
||||
{
|
||||
show_err("ERROR : slave %d is in SAFE_OP + ERROR, attempting ack.\n",
|
||||
slave);
|
||||
ec_slave[slave].state = (EC_STATE_SAFE_OP + EC_STATE_ACK);
|
||||
ec_writestate(slave);
|
||||
}
|
||||
else if (ec_slave[slave].state == EC_STATE_SAFE_OP)
|
||||
{
|
||||
show_err("WARNING : slave %d is in SAFE_OP, change to OPERATIONAL.\n",
|
||||
slave);
|
||||
ec_slave[slave].state = EC_STATE_OPERATIONAL;
|
||||
ec_writestate(slave);
|
||||
}
|
||||
else if (ec_slave[slave].state > EC_STATE_NONE)
|
||||
{
|
||||
if (ec_reconfig_slave(slave, EC_TIMEOUTMON))
|
||||
{
|
||||
ec_slave[slave].islost = FALSE;
|
||||
show_err("MESSAGE : slave %d reconfigured\n", slave);
|
||||
}
|
||||
}
|
||||
else if (!ec_slave[slave].islost)
|
||||
{
|
||||
/* re-check state */
|
||||
ec_statecheck(slave, EC_STATE_OPERATIONAL, EC_TIMEOUTRET);
|
||||
if (ec_slave[slave].state == EC_STATE_NONE)
|
||||
{
|
||||
ec_slave[slave].islost = TRUE;
|
||||
show_err("ERROR : slave %d lost\n", slave);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ec_slave[slave].islost)
|
||||
{
|
||||
if (ec_slave[slave].state == EC_STATE_NONE)
|
||||
{
|
||||
if (ec_recover_slave(slave, EC_TIMEOUTMON))
|
||||
{
|
||||
ec_slave[slave].islost = FALSE;
|
||||
show_err("MESSAGE : slave %d recovered\n", slave);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ec_slave[slave].islost = FALSE;
|
||||
show_err("MESSAGE : slave %d found\n", slave);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ec_group[currentgroup].docheckstate)
|
||||
show_err("OK : all slaves resumed OPERATIONAL.\n");
|
||||
}
|
||||
osal_usleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
#define stack64k (64 * 1024)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
cycletime = 50;
|
||||
step_time = TEST_STEP_CYCLETIME;
|
||||
|
||||
printf("SOEM (Simple Open EtherCAT Master)\nIO test for TJ30-XXXX\n");
|
||||
switch (argc)
|
||||
{
|
||||
case 4:
|
||||
step_time = atoi(argv[3]) * 1000;
|
||||
[[fallthrough]];
|
||||
case 3:
|
||||
cycletime = atoi(argv[2]);
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
dorun = 0;
|
||||
/* create RT thread */
|
||||
osal_thread_create_rt(&thread1, stack64k * 2, &ecatthread, (void *)&cycletime);
|
||||
|
||||
/* create thread to handle slave error handling in OP */
|
||||
osal_thread_create(&thread2, stack64k * 4, &ecatcheck, NULL);
|
||||
|
||||
/* start acyclic part */
|
||||
tj30_test(argv[1]);
|
||||
break;
|
||||
default:
|
||||
printf("Usage: tj30_test ifname [cycletime [step_time]]\n"
|
||||
"ifname = eth0 for example\n"
|
||||
"cycletime in us (default is 50us)\n"
|
||||
"step_time in ms (default is 75ms)");
|
||||
|
||||
ec_adaptert *adapter = NULL;
|
||||
printf("\nAvailable adapters:\n");
|
||||
adapter = ec_find_adapters();
|
||||
while (adapter != NULL)
|
||||
{
|
||||
printf(" - %s (%s)\n", adapter->name, adapter->desc);
|
||||
adapter = adapter->next;
|
||||
}
|
||||
ec_free_adapters(adapter);
|
||||
}
|
||||
return (0);
|
||||
}
|
|
@ -250,7 +250,7 @@ void add_timespec(struct timespec *ts, int64 addtime)
|
|||
sec = (addtime - nsec) / NSEC_PER_SEC;
|
||||
ts->tv_sec += sec;
|
||||
ts->tv_nsec += nsec;
|
||||
if ( ts->tv_nsec > NSEC_PER_SEC )
|
||||
if ( ts->tv_nsec >= NSEC_PER_SEC )
|
||||
{
|
||||
nsec = ts->tv_nsec % NSEC_PER_SEC;
|
||||
ts->tv_sec += (ts->tv_nsec - nsec) / NSEC_PER_SEC;
|
||||
|
|
Loading…
Reference in New Issue