Other Parts Discussed in Thread: LP-AM243, DP83869, UNIFLASH
Tool/software:
I download motor_control_sdk_am243x_09_02_00_11 and use ethercat_slave_simple_demo_am243x-lp_r5fss0-0_freertos_ti-arm-clang project.
I try to write a ethercat master demo on igh ethercat。but when runing ,I have some errors。
AM243X log:
Friendly Version: <KB OSAL v00.01.02.02> Source Id: <5e1ebb0ccfdbbbe7667ebf41c1452faab7e5228b> ********************************************************************* State change: 0x0 -> 0x1 SSC_checkTimer:MaxD:9267640 (9) SSC_checkTimer:MaxET:4 SSC_checkTimer:MaxD:11999745 (11) State change: 0x1 -> 0x2 State change: 0x2 -> 0x1 State change: 0x1 -> 0x2 State change: 0x2 -> 0x1 State change: 0x1 -> 0x2
master log:
Requesting master... Creating slave configurations... Activating master... Starting my_task... [ 6729.946106] EtherCAT ERROR 0-0: Reception of CoE download response failed: No response. [ 6729.951106] EtherCAT ERROR 0-0: Failed to set SAFEOP state, slave refused state change (PREOP + ERROR). [ 6729.953105] EtherCAT ERROR 0-0: AL status message 0x001E: "Invalid input configuration".
demo code.
/*****************************************************************************
*
* Copyright (C) 2009-2010 Moehwald GmbH B. Benner
* 2011 IgH Andreas Stewering-Bone
* 2012 Florian Pose <fp@igh.de>
*
* This file is part of the IgH EtherCAT master
*
* The IgH EtherCAT Master is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* The IgH EtherCAT master is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the IgH EtherCAT master. If not, see <http://www.gnu.org/licenses/>.
*
****************************************************************************/
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
#ifdef XENOMAI_API_V3
#include <alchemy/task.h>
#include <alchemy/sem.h>
enum {T_FPU = 0};
#else
#include <rtdm/rtdm.h>
#include <native/task.h>
#include <native/sem.h>
#include <native/mutex.h>
#include <native/timer.h>
#include <rtdk.h>
#endif
#include <pthread.h>
#include <time.h>
#include "ecrt.h"
RT_TASK my_task;
static volatile sig_atomic_t run = 1;
/****************************************************************************/
// EtherCAT
static ec_master_t *master = NULL;
static ec_master_state_t master_state = {};
static ec_domain_t *domain1 = NULL;
static ec_domain_state_t domain1_state = {};
static uint8_t *domain1_pd = NULL;
static ec_slave_config_t *sc_dig_out_01 = NULL;
/****************************************************************************/
// process data
#define TISlaveDemo_Pos 0, 0
//TI EtherCAT Toolkit for AM243X.R5F
#define Beckhoff_TI_AM243X 0xe000059D, 0x54490025
// offsets for PDO entries
static unsigned int off_dig_out0 = 0;
// process data
const static ec_pdo_entry_reg_t domain1_regs[] = {
{TISlaveDemo_Pos, Beckhoff_TI_AM243X, 0x2000, 0x02, &off_dig_out0, NULL},
{}
};
/****************************************************************************/
/* Slave 1, "TI"
* Vendor ID: 0xe000059D
* Product code: 0x54490025
* Revision number: 0x00010000
*/
const ec_pdo_entry_info_t master_pdo_entries[] = {
{0x2000, 0x02, 8},
{0x2000, 0x03, 8},
{0x2000, 0x04, 16},
{0x2000, 0x01, 32},
{0x2002, 0x02, 8},
{0x2002, 0x04, 16},
{0x2002, 0x03, 8},
{0x2002, 0x01, 32},
};
const ec_pdo_info_t master_pdos[] = {
{0x1600, 3, master_pdo_entries},
{0x1601, 1, master_pdo_entries + 3},
{0x1A00, 3, master_pdo_entries + 4},
{0x1A01, 1, master_pdo_entries + 7},
};
ec_sync_info_t slave_1_syncs[] = {
{0, EC_DIR_OUTPUT, 2, master_pdos + 0, EC_WD_ENABLE},
{1, EC_DIR_INPUT, 2, master_pdos + 2, EC_WD_ENABLE},
{0xff}
};
/*****************************************************************************
* Realtime task
****************************************************************************/
void rt_check_domain_state(void)
{
ec_domain_state_t ds = {};
ecrt_domain_state(domain1, &ds);
if (ds.working_counter != domain1_state.working_counter) {
rt_printf("Domain1: WC %u.\n", ds.working_counter);
}
if (ds.wc_state != domain1_state.wc_state) {
rt_printf("Domain1: State %u.\n", ds.wc_state);
}
domain1_state = ds;
}
/****************************************************************************/
void rt_check_master_state(void)
{
ec_master_state_t ms;
ecrt_master_state(master, &ms);
if (ms.slaves_responding != master_state.slaves_responding) {
rt_printf("%u slave(s).\n", ms.slaves_responding);
}
if (ms.al_states != master_state.al_states) {
rt_printf("AL states: 0x%02X.\n", ms.al_states);
}
if (ms.link_up != master_state.link_up) {
rt_printf("Link is %s.\n", ms.link_up ? "up" : "down");
}
master_state = ms;
}
/****************************************************************************/
void my_task_proc(void *arg)
{
int cycle_counter = 0;
int time_counter = 0;
unsigned int blink = 0;
struct timespec start, end;
double tx_time = 0;
double rx_time = 0;
double tx_min_time = 0;
double tx_max_time = 0;
double rx_min_time = 0;
double rx_max_time = 0;
double tx_avg_time = 0;
double rx_avg_time = 0;
double tx_total_time = 0;
double rx_total_time = 0;
int rx_init = 0;
int tx_init = 0;
int warmup = 0;
rt_task_set_periodic(NULL, TM_NOW, 1000000); // ns
while (run) {
rt_task_wait_period(NULL);
cycle_counter++;
clock_gettime(CLOCK_MONOTONIC, &start);
// receive EtherCAT frames
ecrt_master_receive(master);
clock_gettime(CLOCK_MONOTONIC, &end);
ecrt_domain_process(domain1);
if(warmup > 2) /* wait 2s */
{
time_counter++;
rx_time = ((end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec))/1000;
if(!rx_init)
{
rx_init = 1;
rx_min_time = rx_time;
}
if(rx_time < rx_min_time)
{
rx_min_time = rx_time;
}
if(rx_time > rx_max_time)
{
rx_max_time = rx_time;
printf("[rx max]: max:%.2f us\n",rx_max_time);
}
rx_total_time += rx_time;
rx_avg_time = rx_total_time/time_counter;
}
rt_check_domain_state();
if (!(cycle_counter % 1000)) {
warmup++;
rt_check_master_state();
if(warmup > 2) /* wait 2s */
{
printf("[rx]: curr:%.2f us | min:%.2f us | avg:%.2f us | max:%.2f us\n", rx_time, rx_min_time, rx_avg_time, rx_max_time);
printf("[tx]: curr:%.2f us | min:%.2f us | avg:%.2f us | max:%.2f us\n", tx_time, tx_min_time, tx_avg_time, tx_max_time);
}
}
if (!(cycle_counter % 200)) {
blink = !blink;
}
EC_WRITE_U8(domain1_pd + off_dig_out0, blink ? 0x0 : 0x0F);
// send process data
ecrt_domain_queue(domain1);
clock_gettime(CLOCK_MONOTONIC, &start);
ecrt_master_send(master);
clock_gettime(CLOCK_MONOTONIC, &end);
if(warmup > 2) /* wait 2s */
{
tx_time = ((end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec))/1000;
if(!tx_init)
{
tx_init = 1;
tx_min_time = tx_time;
}
tx_avg_time += tx_time;
if(tx_time < tx_min_time)
{
tx_min_time = tx_time;
}
if(tx_time > tx_max_time)
{
tx_max_time = tx_time;
printf("[tx max]: max:%.2f us\n",tx_max_time);
}
tx_total_time += tx_time;
tx_avg_time = tx_total_time/time_counter;
}
}
}
/****************************************************************************
* Signal handler
***************************************************************************/
void signal_handler(int sig)
{
run = 0;
}
/****************************************************************************
* Main function
***************************************************************************/
int main(int argc, char *argv[])
{
ec_slave_config_t *sc;
int ret;
#ifndef XENOMAI_API_V3
/* Perform auto-init of rt_print buffers if the task doesn't do so */
rt_print_auto_init(1);
#endif
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
mlockall(MCL_CURRENT | MCL_FUTURE);
printf("Requesting master...\n");
master = ecrt_request_master(0);
if (!master) {
return -1;
}
domain1 = ecrt_master_create_domain(master);
if (!domain1) {
return -1;
}
printf("Creating slave configurations...\n");
sc_dig_out_01 =
ecrt_master_slave_config(master, TISlaveDemo_Pos, Beckhoff_TI_AM243X);
if (!sc_dig_out_01) {
fprintf(stderr, "Failed to get slave configuration.\n");
return -1;
}
if (ecrt_slave_config_pdos(sc_dig_out_01, EC_END, slave_1_syncs)) {
fprintf(stderr, "Failed to configure PDOs.\n");
return -1;
}
if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
fprintf(stderr, "PDO entry registration failed!\n");
return -1;
}
printf("Activating master...\n");
if (ecrt_master_activate(master)) {
return -1;
}
if (!(domain1_pd = ecrt_domain_data(domain1))) {
fprintf(stderr, "Failed to get domain data pointer.\n");
return -1;
}
ret = rt_task_create(&my_task, "my_task", 0, 80, T_FPU);
if (ret < 0) {
fprintf(stderr, "Failed to create task: %s\n", strerror(-ret));
return -1;
}
printf("Starting my_task...\n");
ret = rt_task_start(&my_task, &my_task_proc, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to start task: %s\n", strerror(-ret));
return -1;
}
while (run) {
sched_yield();
}
printf("Deleting realtime task...\n");
rt_task_delete(&my_task);
printf("End of Program\n");
ecrt_release_master(master);
return 0;
}
/****************************************************************************/
I don't know what's reason, Can you provide a sample master demo based on igh ethercat?
















