Преглед изворни кода

update: update cmd

Signed-off-by: sakumisu <1203593632@qq.com>
sakumisu пре 3 месеци
родитељ
комит
06bb6c0d31
10 измењених фајлова са 195 додато и 50 уклоњено
  1. 1 4
      CMakeLists.txt
  2. 3 2
      README.md
  3. 1 0
      README_zh.md
  4. 1 3
      SConscript
  5. 0 1
      demo/hpmicro/CMakeLists.txt
  6. 57 9
      demo/hpmicro/main.c
  7. 1 0
      include/ec_slave.h
  8. 128 30
      src/ec_cmd.c
  9. 1 1
      src/ec_common.c
  10. 2 0
      src/ec_perf.c

+ 1 - 4
CMakeLists.txt

@@ -5,6 +5,7 @@ if(CONFIG_CHERRYECAT)
     )
 
     list(APPEND cherryec_srcs
+        ${CMAKE_CURRENT_LIST_DIR}/src/ec_cmd.c
         ${CMAKE_CURRENT_LIST_DIR}/src/ec_coe.c
         ${CMAKE_CURRENT_LIST_DIR}/src/ec_common.c
         ${CMAKE_CURRENT_LIST_DIR}/src/ec_datagram.c
@@ -16,10 +17,6 @@ if(CONFIG_CHERRYECAT)
         ${CMAKE_CURRENT_LIST_DIR}/src/ec_slave.c
     )
 
-    if(CONFIG_CHERRYECAT_CMD)
-        list(APPEND cherryec_srcs ${CMAKE_CURRENT_LIST_DIR}/src/ec_cmd.c)
-    endif()
-
     if(DEFINED CONFIG_CHERRYECAT_OSAL)
         if("${CONFIG_CHERRYECAT_OSAL}" STREQUAL "freertos")
             list(APPEND cherryec_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/ec_osal_freertos.c)

+ 3 - 2
README.md

@@ -24,14 +24,15 @@ CherryECAT is a tiny and beautiful, high real-time and low-jitter EtherCAT maste
 - Support Slave register access
 - Support multi master
 - Support backup redundancy
-- Support ethercat cmd in shell, ref to IGH
+- Minimum PDO cyclic time < 40 us (depends on master and slave hardware)
+- Support ethercat cmd with shell, ref to IgH
 
 ## Hardware limitations
 
 - **Master**
 	- CPU (cache > 16K, memcpy speed > 100MB/s)
 	- ENET must support descriptor dma and iperf with lwip > 90 Mbps
-	- Code must run in ram
+	- Code must run in ram, ignore if no dc
 	- Must support High-Precision Timer (jitter < 1us)
 	- Must support High-Precision timestamp (like ARM DWT)
 	- Must support long long print

+ 1 - 0
README_zh.md

@@ -24,6 +24,7 @@ CherryECAT 是一个小而美的、高实时性、低抖动的 EtherCAT 主机
 - 支持 Slave 寄存器读写
 - 支持多主站
 - 支持备份冗余
+- 最小 PDO cyclic time < 40 us (实际数值受主站硬件和从站硬件影响)
 - 支持 ethercat 命令行交互,参考 IgH
 
 ## 硬件限制

+ 1 - 3
SConscript

@@ -8,6 +8,7 @@ LIBS    = []
 LIBPATH = []
 CPPDEFINES = []
 
+src += Glob('src/ec_cmd.c')
 src += Glob('src/ec_coe.c')
 src += Glob('src/ec_common.c')
 src += Glob('src/ec_datagram.c')
@@ -19,9 +20,6 @@ src += Glob('src/ec_sii.c')
 src += Glob('src/ec_slave.c')
 src += Glob('src/osal/ec_osal_rtthread.c')
 
-if GetDepend(['PKG_CHERRYECAT_CMD']):
-    src += Glob('src/ec_cmd.c')
-
 group = DefineGroup('CherryECAT', src, depend = ['PKG_USING_CHERRYECAT'], LIBS = LIBS, LIBPATH=LIBPATH, CPPPATH = path, CPPDEFINES = CPPDEFINES)
 
 Return('group')

+ 0 - 1
demo/hpmicro/CMakeLists.txt

@@ -20,7 +20,6 @@ set(APP_USE_ENET_PORT_COUNT 1)
 set(APP_USE_ENET_PHY_RTL8201 1)
 
 set(CONFIG_CHERRYECAT 1)
-set(CONFIG_CHERRYECAT_CMD 1)
 set(CONFIG_CHERRYECAT_OSAL "freertos")
 
 if(NOT (HPM_BUILD_TYPE STREQUAL "ram"))

+ 57 - 9
demo/hpmicro/main.c

@@ -100,6 +100,27 @@ static void task_start(void *param)
 
 CSH_CMD_EXPORT(ethercat, );
 
+static ec_pdo_entry_info_t dio_1600[] = {
+    { 0x6000, 0x00, 0x20 },
+};
+
+static ec_pdo_entry_info_t dio_1a00[] = {
+    { 0x7010, 0x00, 0x20 },
+};
+
+static ec_pdo_info_t dio_rxpdos[] = {
+    { 0x1600, 1, &dio_1600[0] },
+};
+
+static ec_pdo_info_t dio_txpdos[] = {
+    { 0x1a00, 1, &dio_1a00[0] },
+};
+
+static ec_sync_info_t dio_syncs[] = {
+    { 2, EC_DIR_OUTPUT, 1, dio_rxpdos },
+    { 3, EC_DIR_INPUT, 1, dio_txpdos },
+};
+
 static ec_pdo_entry_info_t coe402_1602[] = {
     { 0x6040, 0x00, 0x10 },
     { 0x60ff, 0x00, 0x20 },
@@ -127,7 +148,8 @@ static ec_sync_info_t cia402_syncs[] = {
 
 int ec_start(int argc, const char **argv)
 {
-    static ec_slave_config_t slave_config;
+    static ec_slave_config_t slave_cia402_config;
+    static ec_slave_config_t slave_dio_config;
 
     if (g_ec_master.slave_count == 0) {
         printf("No slave found, please check the connection\r\n");
@@ -139,18 +161,44 @@ int ec_start(int argc, const char **argv)
         return -1;
     }
 
-    slave_config.dc_assign_activate = 0x300;
+    slave_cia402_config.dc_assign_activate = 0x300;
+
+    slave_cia402_config.dc_sync[0].cycle_time = atoi(argv[1]) * 1000;
+    slave_cia402_config.dc_sync[0].shift_time = 1000000;
+    slave_cia402_config.dc_sync[1].cycle_time = 0;
+    slave_cia402_config.dc_sync[1].shift_time = 0;
+
+    slave_cia402_config.sync = cia402_syncs;
+    slave_cia402_config.sync_count = sizeof(cia402_syncs) / sizeof(ec_sync_info_t);
 
-    slave_config.dc_sync[0].cycle_time = atoi(argv[1]) * 1000;
-    slave_config.dc_sync[0].shift_time = 1000000;
-    slave_config.dc_sync[1].cycle_time = 0;
-    slave_config.dc_sync[1].shift_time = 0;
+    slave_dio_config.dc_assign_activate = 0x300;
 
-    slave_config.sync = cia402_syncs;
-    slave_config.sync_count = sizeof(cia402_syncs) / sizeof(ec_sync_info_t);
+    slave_dio_config.dc_sync[0].cycle_time = atoi(argv[1]) * 1000;
+    slave_dio_config.dc_sync[0].shift_time = 1000000;
+    slave_dio_config.dc_sync[1].cycle_time = 0;
+    slave_dio_config.dc_sync[1].shift_time = 0;
+    slave_dio_config.sync = dio_syncs;
+    slave_dio_config.sync_count = sizeof(dio_syncs) / sizeof(ec_sync_info_t);
 
     for (uint32_t i = 0; i < g_ec_master.slave_count; i++) {
-        g_ec_master.slaves[i].config = &slave_config;
+        if (g_ec_master.slaves[i].sii.vendor_id != 0x0048504D) { // HPMicro
+            EC_LOG_ERR("Unsupported slave found: vendor_id=0x%08x\n", g_ec_master.slaves[i].sii.vendor_id);
+            return -1;
+        }
+
+        switch (g_ec_master.slaves[i].sii.product_code) {
+            case 0x00000001: // DIO
+                g_ec_master.slaves[i].config = &slave_dio_config;
+                break;
+            case 0x00000002: // FOE
+                break;
+            case 0x00000003: // CIA402
+                g_ec_master.slaves[i].config = &slave_cia402_config;
+                break;
+
+            default:
+                break;
+        }
     }
 
     ec_master_start(&g_ec_master, atoi(argv[1]));

+ 1 - 0
include/ec_slave.h

@@ -107,5 +107,6 @@ typedef struct ec_slave {
 } ec_slave_t;
 
 void ec_slaves_scanning(ec_master_t *master);
+char *ec_slave_get_sii_string(const ec_slave_t *slave, uint32_t index);
 
 #endif

+ 128 - 30
src/ec_cmd.c

@@ -5,7 +5,7 @@
  */
 #include "ec_master.h"
 
-#define EC_IOCTL_STRING_SIZE 64
+#ifdef CONFIG_EC_CMD_ENABLE
 
 typedef struct {
     uint32_t slave_count;
@@ -77,10 +77,10 @@ typedef struct {
     uint8_t sync_count;
     uint16_t sdo_count;
     uint32_t sii_nwords;
-    char group[EC_IOCTL_STRING_SIZE];
-    char image[EC_IOCTL_STRING_SIZE];
-    char order[EC_IOCTL_STRING_SIZE];
-    char name[EC_IOCTL_STRING_SIZE];
+    char *group;
+    char *image;
+    char *order;
+    char *name;
 } ec_cmd_slave_info_t;
 
 static ec_master_t *global_cmd_master = NULL;
@@ -92,27 +92,31 @@ void ec_master_cmd_init(ec_master_t *master)
 
 static void ec_master_cmd_show_help(void)
 {
-    EC_LOG_RAW("CherryECAT " CHERRYECAT_VERSION_STR " Command Line Tool\n");
-    EC_LOG_RAW("Usage: ethercat <command> [options]\n\n");
+    EC_LOG_RAW("CherryECAT " CHERRYECAT_VERSION_STR " Command Line Tool\n\n");
+    EC_LOG_RAW("Usage: ethercat <command> [options]\n");
     EC_LOG_RAW("Commands:\n");
-    EC_LOG_RAW("  master                  Show master information\n");
-    EC_LOG_RAW("  slaves                  Show slaves overview\n");
-    EC_LOG_RAW("  slaves -v               Show detailed information for all slaves\n");
-    EC_LOG_RAW("  slaves -p <idx>         Show information for slave <idx>\n");
-    EC_LOG_RAW("  slaves -p <idx> -v      Show detailed information for slave <idx>\n");
-    EC_LOG_RAW("  pdos                    Show PDOs for all slaves\n");
-    EC_LOG_RAW("  pdos -p <idx>           Show PDOs for slave <idx>\n");
-    EC_LOG_RAW("  states <state>          Request state for all slaves (hex)\n");
-    EC_LOG_RAW("  states -p <idx> <state> Request state for slave <idx> (hex)\n");
-    EC_LOG_RAW("  coe_read -p [idx] [index] [subindex] Read SDO via CoE\n");
-    EC_LOG_RAW("  coe_write -p [idx] [index] [subindex] [value] Write SDO via CoE\n");
-    EC_LOG_RAW("  sii_read -p [idx]       Read SII\n");
-    EC_LOG_RAW("  wc                      Show master working counter\n");
+    EC_LOG_RAW("  master                                         Show master information\n");
+    EC_LOG_RAW("  slaves                                         Show slaves overview\n");
+    EC_LOG_RAW("  slaves -v                                      Show detailed information for all slaves\n");
+    EC_LOG_RAW("  slaves -p <idx>                                Show information for slave <idx>\n");
+    EC_LOG_RAW("  slaves -p <idx> -v                             Show detailed information for slave <idx>\n");
+    EC_LOG_RAW("  pdos                                           Show PDOs for all slaves\n");
+    EC_LOG_RAW("  pdos -p <idx>                                  Show PDOs for slave <idx>\n");
+    EC_LOG_RAW("  states <state>                                 Request state for all slaves (hex)\n");
+    EC_LOG_RAW("  states -p <idx> <state>                        Request state for slave <idx> (hex)\n");
+    EC_LOG_RAW("  coe_read -p [idx] [index] [subindex]           Read SDO via CoE\n");
+    EC_LOG_RAW("  coe_write -p [idx] [index] [subindex] [value]  Write SDO via CoE\n");
+    EC_LOG_RAW("  pdo_read                                       Read process data\n");
+    EC_LOG_RAW("  pdo_read -p [idx]                              Read slave <idx> process data\n");
+    EC_LOG_RAW("  pdo_write [offset] [data]                      Write process data with offset\n");
+    EC_LOG_RAW("  pdo_write -p [idx] [offset] [data]             Write slave <idx> process data with offset\n");
+    EC_LOG_RAW("  sii_read -p [idx]                              Read SII\n");
+    EC_LOG_RAW("  wc                                             Show master working counter\n");
 #ifdef CONFIG_EC_PERF_ENABLE
-    EC_LOG_RAW("  perf -s <time>          Start performance test\n");
-    EC_LOG_RAW("  perf -v                 Show performance statistics\n");
+    EC_LOG_RAW("  perf -s <time>                                 Start performance test\n");
+    EC_LOG_RAW("  perf -v                                        Show performance statistics\n");
 #endif
-    EC_LOG_RAW("  help                    Show this help\n\n");
+    EC_LOG_RAW("  help                                           Show this help\n\n");
 }
 
 static const char *ec_slave_state_string(uint8_t state)
@@ -249,6 +253,11 @@ static void ec_master_get_slave_info(ec_slave_t *slave, ec_cmd_slave_info_t *inf
     info->has_dc_system_time = slave->has_dc_system_time;
     info->transmission_delay = slave->transmission_delay;
     info->current_state = slave->current_state;
+
+    info->group = ec_slave_get_sii_string(slave, slave->sii.general.groupidx);
+    info->image = ec_slave_get_sii_string(slave, slave->sii.general.imgidx);
+    info->order = ec_slave_get_sii_string(slave, slave->sii.general.orderidx);
+    info->name = ec_slave_get_sii_string(slave, slave->sii.general.nameidx);
 }
 
 void ec_master_cmd_master(ec_master_t *master)
@@ -398,7 +407,7 @@ static void ec_cmd_show_slave_detail(ec_master_t *master, uint32_t slave_idx)
     EC_LOG_RAW("=== Master %d, Slave %d ===\n", master->index, slave_idx);
 
     if (data.alias != 0) {
-        EC_LOG_RAW("Alias: %d\n", data.alias != 0);
+        EC_LOG_RAW("Alias: 0x%04x\n", data.alias);
     }
 
     EC_LOG_RAW("Device: %s\n", master->netdev[slave->netdev_idx]->name);
@@ -483,10 +492,10 @@ static void ec_cmd_show_slave_detail(ec_master_t *master, uint32_t slave_idx)
 
     if (data.has_general) {
         EC_LOG_RAW("General:\n");
-        // EC_LOG_RAW("  Group: %s\n", data.sii.group ? data.sii.group : "");
-        // EC_LOG_RAW("  Image name: %s\n", data.sii.image ? data.sii.image : "");
-        // EC_LOG_RAW("  Order number: %s\n", data.sii.order ? data.sii.order : "");
-        // EC_LOG_RAW("  Device name: %s\n", data.sii.name ? data.sii.name : "");
+        EC_LOG_RAW("  Group: %s\n", data.group ? data.group : "");
+        EC_LOG_RAW("  Image name: %s\n", data.image ? data.image : "");
+        EC_LOG_RAW("  Order number: %s\n", data.order ? data.order : "");
+        EC_LOG_RAW("  Device name: %s\n", data.name ? data.name : "");
 
         if (data.mailbox_protocols & EC_MBXPROT_COE) {
             EC_LOG_RAW("  CoE details:\n");
@@ -731,7 +740,7 @@ int ethercat(int argc, const char **argv)
         ec_datagram_clear(&datagram);
 
         return 0;
-    } else if (argc >= 6 && strcmp(argv[1], "coe_write") == 0) {
+    } else if (argc >= 7 && strcmp(argv[1], "coe_write") == 0) {
         // ethercat coe_write -p [slave_idx] [index] [subindex] [u32data]
         static ec_datagram_t datagram;
         uint32_t u32data;
@@ -779,10 +788,99 @@ int ethercat(int argc, const char **argv)
                    global_cmd_master->slaves[slave_idx].sii_nwords * 2);
 
         return 0;
+    } else if (argc >= 2 && strcmp(argv[1], "pdo_read") == 0) {
+        // ethercat pdo_read
+        if (argc == 2) {
+            for (uint32_t count = 0; count < 10; count++) {
+                EC_LOG_RAW("\r");
+                for (uint32_t i = 0; i < global_cmd_master->actual_pdo_size; i++) {
+                    EC_LOG_RAW("%02x ", global_cmd_master->pdo_buffer[EC_NETDEV_MAIN][i]);
+                }
+                //fflush(stdout);
+                if (count < 9) {
+                    ec_osal_msleep(1000);
+                }
+            }
+            EC_LOG_RAW("\n");
+            return 0;
+        } else if (argc == 4 && strcmp(argv[2], "-p") == 0) {
+            // ethercat pdo_read -p [slave_idx]
+            uint32_t slave_idx = atoi(argv[3]);
+            if (slave_idx >= global_cmd_master->slave_count) {
+                EC_LOG_RAW("No slaves found\n");
+                return -1;
+            }
+            uint8_t *buffer = ec_master_get_slave_domain(global_cmd_master, slave_idx);
+            uint32_t data_size = ec_master_get_slave_domain_size(global_cmd_master, slave_idx);
+
+            for (uint32_t count = 0; count < 10; count++) {
+                EC_LOG_RAW("\r");
+                for (uint32_t i = 0; i < data_size; i++) {
+                    EC_LOG_RAW("%02x ", buffer[i]);
+                }
+                //fflush(stdout);
+                if (count < 9) {
+                    ec_osal_msleep(1000);
+                }
+            }
+            EC_LOG_RAW("\n");
+            return 0;
+        } else {
+        }
+    } else if (argc >= 4 && strcmp(argv[1], "pdo_write") == 0) {
+        // ethercat pdo_write -p [slave_idx] [offset] [data]
+        if (argc >= 6 && strcmp(argv[2], "-p") == 0) {
+            uint32_t slave_idx = atoi(argv[3]);
+            if (slave_idx >= global_cmd_master->slave_count) {
+                EC_LOG_RAW("No slaves found\n");
+                return -1;
+            }
+
+            uint32_t offset = strtol(argv[4], NULL, 16);
+            uint32_t data = strtol(argv[5], NULL, 16);
+            uint32_t size;
+
+            if (data < 0xff)
+                size = 1;
+            else if (data < 0xffff)
+                size = 2;
+            else
+                size = 4;
+
+            uint8_t *buffer = ec_master_get_slave_domain(global_cmd_master, slave_idx);
+
+            ec_memcpy(&buffer[offset], &data, size);
+
+            return 0;
+        } else {
+            uint32_t offset = strtol(argv[2], NULL, 16);
+            uint32_t data = strtol(argv[3], NULL, 16);
+            uint32_t size;
+
+            if (data < 0xff)
+                size = 1;
+            else if (data < 0xffff)
+                size = 2;
+            else
+                size = 4;
+
+            for (uint32_t slave_idx = 0; slave_idx < global_cmd_master->slave_count; slave_idx++) {
+                uint8_t *buffer = ec_master_get_slave_domain(global_cmd_master, slave_idx);
+                ec_memcpy(&buffer[offset], &data, size);
+            }
+            return 0;
+        }
     } else {
     }
 
     EC_LOG_RAW("Invalid command: %s\n", argv[1]);
     ec_master_cmd_show_help();
     return -1;
-}
+}
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+MSH_CMD_EXPORT(ethercat, cherryecat command line tool);
+#endif
+
+#endif

+ 1 - 1
src/ec_common.c

@@ -125,7 +125,7 @@ typedef struct {
 
 const char *ec_state_string(uint8_t states, uint8_t multi)
 {
-    off_t off = 0;
+    uint32_t off = 0;
     unsigned int first = 1;
     static char buffer[64];
 

+ 2 - 0
src/ec_perf.c

@@ -5,6 +5,7 @@
  */
 #include "ec_master.h"
 
+#ifdef CONFIG_EC_PERF_ENABLE
 void ec_perf_init(ec_perf_t *perf, uint64_t expected_interval_us)
 {
     memset(perf, 0, sizeof(ec_perf_t));
@@ -76,3 +77,4 @@ void ec_perf_print_statistics(ec_perf_t *perf)
 
     EC_LOG_RAW("===================================\n");
 }
+#endif