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/latex
|
||||||
/doc/html
|
/doc/html
|
||||||
tags
|
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)
|
cmake_minimum_required(VERSION 3.9)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules")
|
||||||
|
# SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
|
||||||
|
|
||||||
project(SOEM
|
project(SOEM
|
||||||
DESCRIPTION "Simple Open EtherCAT Master"
|
DESCRIPTION "Simple Open EtherCAT Master"
|
||||||
VERSION 1.4.0
|
VERSION 1.4.0
|
||||||
|
@ -33,7 +35,7 @@ if(WIN32)
|
||||||
set(OS_LIBS wpcap.lib Packet.lib Ws2_32.lib Winmm.lib)
|
set(OS_LIBS wpcap.lib Packet.lib Ws2_32.lib Winmm.lib)
|
||||||
elseif(UNIX AND NOT APPLE)
|
elseif(UNIX AND NOT APPLE)
|
||||||
set(OS "linux")
|
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)
|
set(OS_LIBS pthread rt)
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
# This must come *before* linux or MacOSX will identify as Unix.
|
# This must come *before* linux or MacOSX will identify as Unix.
|
||||||
|
@ -106,8 +108,10 @@ install(FILES
|
||||||
DESTINATION ${SOEM_INCLUDE_INSTALL_DIR})
|
DESTINATION ${SOEM_INCLUDE_INSTALL_DIR})
|
||||||
|
|
||||||
if(BUILD_TESTS)
|
if(BUILD_TESTS)
|
||||||
add_subdirectory(test/simple_ng)
|
# add_subdirectory(test/simple_ng)
|
||||||
add_subdirectory(test/linux/slaveinfo)
|
add_subdirectory(test/linux/ecslaveinfo)
|
||||||
add_subdirectory(test/linux/eepromtool)
|
add_subdirectory(test/linux/eceeprom)
|
||||||
add_subdirectory(test/linux/simple_test)
|
# add_subdirectory(test/linux/simple_test)
|
||||||
|
add_subdirectory(test/linux/tj30_test)
|
||||||
|
# add_subdirectory(test/linux/red_test)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -54,7 +54,7 @@ boolean osal_timer_is_expired (osal_timert * self)
|
||||||
stop_time.tv_usec = self->stop_time.usec;
|
stop_time.tv_usec = self->stop_time.usec;
|
||||||
is_not_yet_expired = timercmp (¤t_time, &stop_time, <);
|
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)
|
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;
|
aFOEp = (ec_FOEt *)&MbxIn;
|
||||||
FOEp = (ec_FOEt *)&MbxOut;
|
FOEp = (ec_FOEt *)&MbxOut;
|
||||||
fnsize = (uint16)strlen(filename);
|
fnsize = (uint16)strlen(filename);
|
||||||
|
if (fnsize > EC_MAXFOEDATA)
|
||||||
|
{
|
||||||
|
fnsize = EC_MAXFOEDATA;
|
||||||
|
}
|
||||||
maxdata = context->slavelist[slave].mbx_l - 12;
|
maxdata = context->slavelist[slave].mbx_l - 12;
|
||||||
if (fnsize > maxdata)
|
if (fnsize > maxdata)
|
||||||
{
|
{
|
||||||
|
@ -216,6 +220,10 @@ int ecx_FOEwrite(ecx_contextt *context, uint16 slave, char *filename, uint32 pas
|
||||||
FOEp = (ec_FOEt *)&MbxOut;
|
FOEp = (ec_FOEt *)&MbxOut;
|
||||||
dofinalzero = TRUE;
|
dofinalzero = TRUE;
|
||||||
fnsize = (uint16)strlen(filename);
|
fnsize = (uint16)strlen(filename);
|
||||||
|
if (fnsize > EC_MAXFOEDATA)
|
||||||
|
{
|
||||||
|
fnsize = EC_MAXFOEDATA;
|
||||||
|
}
|
||||||
maxdata = context->slavelist[slave].mbx_l - 12;
|
maxdata = context->slavelist[slave].mbx_l - 12;
|
||||||
if (fnsize > maxdata)
|
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;
|
sec = (addtime - nsec) / NSEC_PER_SEC;
|
||||||
ts->tv_sec += sec;
|
ts->tv_sec += sec;
|
||||||
ts->tv_nsec += nsec;
|
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;
|
nsec = ts->tv_nsec % NSEC_PER_SEC;
|
||||||
ts->tv_sec += (ts->tv_nsec - 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
|
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");
|
printf ("Available adapters\n");
|
||||||
adapter = ec_find_adapters ();
|
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;
|
sec = (addtime - nsec) / NSEC_PER_SEC;
|
||||||
ts->tv_sec += sec;
|
ts->tv_sec += sec;
|
||||||
ts->tv_nsec += nsec;
|
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;
|
nsec = ts->tv_nsec % NSEC_PER_SEC;
|
||||||
ts->tv_sec += (ts->tv_nsec - nsec) / NSEC_PER_SEC;
|
ts->tv_sec += (ts->tv_nsec - nsec) / NSEC_PER_SEC;
|
||||||
|
|
Loading…
Reference in New Issue