improve firmware update example (can handle write while busy and wait for slaves which update in BOOT2INIT transition

pull/56/head
Sebastian Block 2016-08-26 15:21:31 +02:00
parent 8f1cc8dad0
commit f7dce28f68
2 changed files with 128 additions and 19 deletions

View File

@ -0,0 +1,14 @@
set(SOURCES firm_update.c)
add_executable(firm_update ${SOURCES})
target_link_libraries(firm_update soem)
if(WIN32)
target_link_libraries(firm_update wpcap.lib Packet.lib Ws2_32.lib Winmm.lib)
elseif(UNIX)
target_link_libraries(firm_update pthread rt)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "rt-kernel")
target_link_libraries(firm_update "-Wl,--start-group -l${BSP} -l${ARCH} -lkern -ldev -lsio -lblock -lfs -lusb -llwip -leth -li2c -lrtc -lcan -lnand -lspi -lnor -lpwm -ladc -ltrace -lc -lm -Wl,--end-group")
endif()
install(TARGETS firm_update DESTINATION bin)

View File

@ -20,13 +20,13 @@
#include "ethercat.h"
#define FWBUFSIZE (8 * 1024 * 1024)
#define FWBUFSIZE (20 * 1024 * 1024)
uint8 ob;
uint16 ow;
uint32 data;
char filename[256];
char filebuffer[FWBUFSIZE]; // 8MB buffer
char filebuffer[FWBUFSIZE]; // 20MB buffer
int filesize;
int j;
uint16 argslave;
@ -48,8 +48,9 @@ int input_bin(char *fname, int *length)
}
void boottest(char *ifname, uint16 slave, char *filename)
int boottest(char *ifname, uint16 slave, char *filename)
{
int retval = 0;
printf("Starting firmware update example\n");
/* initialise SOEM, bind socket to ifname */
@ -61,15 +62,47 @@ void boottest(char *ifname, uint16 slave, char *filename)
if ( ec_config_init(FALSE) > 0 )
{
int counter = 3;
char sm_zero[sizeof(ec_smt)*2];
char fmmu_zero[sizeof(ec_fmmut)];
unsigned char rd_stat = 0xff;
memset(sm_zero, 0, sizeof(sm_zero));
memset(fmmu_zero, 0, sizeof(fmmu_zero));
printf("%d slaves found and configured.\n",ec_slavecount);
counter = 3;
do {
/* wait for slave to reach PREOP state */
if (ec_statecheck(slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE * 4) == EC_STATE_PRE_OP) {
printf("Slave is in PREOP state\n");
counter = 0;
}
}
while (counter-- > 0);
counter = 3;
do {
printf("Request init state for slave %d\n", slave);
ec_slave[slave].state = EC_STATE_INIT;
ec_writestate(slave);
/* wait for slave to reach INIT state */
ec_statecheck(slave, EC_STATE_INIT, EC_TIMEOUTSTATE * 4);
printf("Slave %d state to INIT.\n", slave);
if (ec_statecheck(slave, EC_STATE_INIT, EC_TIMEOUTSTATE * 4) == EC_STATE_INIT)
counter = 0;;
}
while (counter-- > 0);
printf("Slave %d state to INIT. counter: %d\n", slave, counter);
/* clean FMMUs */
ec_FPWR(ec_slave[slave].configadr, ECT_REG_FMMU0, sizeof(fmmu_zero), fmmu_zero, EC_TIMEOUTRET3);
ec_FPWR(ec_slave[slave].configadr, ECT_REG_FMMU1, sizeof(fmmu_zero), fmmu_zero, EC_TIMEOUTRET3);
/* clean all SM0 / SM1 to set new bootstrap values later */
ec_FPWR(ec_slave[slave].configadr, ECT_REG_SM0, sizeof(ec_smt) * 2, sm_zero, EC_TIMEOUTRET3);
ec_FPRD(ec_slave[slave].configadr, ECT_REG_SM1STAT, 1, &rd_stat, EC_TIMEOUTRET3);
printf("Read back Status of SM1: %02x\n", rd_stat);
/* read BOOT mailbox data, master -> slave */
data = ec_readeeprom(slave, ECT_SII_BOOTRXMBX, EC_TIMEOUTEEP);
@ -98,9 +131,24 @@ void boottest(char *ifname, uint16 slave, char *filename)
/* program SM1 mailbox out for slave */
ec_FPWR (ec_slave[slave].configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET);
printf("Request BOOT state for slave %d\n", slave);
ec_slave[slave].state = EC_STATE_BOOT;
ec_writestate(slave);
/* give EEPROM control to PDI */
rd_stat = 1;
ec_FPWR (ec_slave[slave].configadr, ECT_REG_EEPCFG, 1, &rd_stat, EC_TIMEOUTRET);
counter = 3;
do {
uint16 ret;
printf("Request BOOT state for slave %d\n", slave);
ec_slave[slave].state = EC_STATE_BOOT;
printf("ec_writestate returned: %d\n", ec_writestate(slave));
ret = ec_statecheck(slave, EC_STATE_BOOT, EC_TIMEOUTSTATE );
printf("ec_statecheck returned: %d\n", ret);
if (ret == EC_STATE_BOOT)
counter = 0;
} while(counter-- > 0);
printf("check BOOT state again\n");
/* wait for slave to reach BOOT state */
if (ec_statecheck(slave, EC_STATE_BOOT, EC_TIMEOUTSTATE * 10) == EC_STATE_BOOT)
@ -109,22 +157,65 @@ void boottest(char *ifname, uint16 slave, char *filename)
if (input_bin(filename, &filesize))
{
char *short_filename = strrchr(filename, '/'); /* search for last / */
if (short_filename)
short_filename++; /* jump over the \ */
else
short_filename = filename; /* no \ found -> must be a short filename */
printf("File read OK, %d bytes.\n",filesize);
printf("FoE write....");
j = ec_FOEwrite(slave, filename, 0, filesize , &filebuffer, EC_TIMEOUTSTATE);
printf("FoE write %s....\n", short_filename);
j = ec_FOEwrite(slave, short_filename, 0, filesize , &filebuffer, EC_TIMEOUTSTATE);
printf("result %d.\n",j);
printf("Request init state for slave %d\n", slave);
ec_slave[slave].state = EC_STATE_INIT;
ec_writestate(slave);
}
else
printf("File not read OK.\n");
}
if (j == 0) retval = 5;
else if (j != 1) retval = j;
if (retval == 0) {
/* wait max 600s => 10 minutes for firmware update to complete */
counter = 60;
retval = 6; /* only success switch to init state afterwards completes firmware update */
do {
uint16 ret;
printf("Request init state for slave %d (counter: %d)\n", slave, counter);
ec_slave[slave].state = EC_STATE_INIT;
ec_writestate(slave);
ret = ec_statecheck(slave, EC_STATE_INIT, 10000000);
if (ret == 0) {
int count;
if ((count = ec_config_init(FALSE)) >= slave) {
ec_slave[slave].state = EC_STATE_INIT;
ec_writestate(slave);
ret = ec_statecheck(slave, EC_STATE_INIT, EC_TIMEOUTSTATE * 10);
}
else {
printf("Slaves found: %d Needed: %d .. will try it again\n", count, slave);
#ifndef WIN32
sleep(10);
#endif
ret = 25555;
}
}
if (ret == EC_STATE_INIT) {
counter = 0;
printf("State change to init success\n");
retval = 0;
}
} while (counter-- > 0);
}
}
else {
printf("File not read OK.\n");
retval = 4;
}
}
else {
printf("Failed to enter boot mode\n");
retval = 3;
}
}
else
{
printf("No slaves found!\n");
retval = 2;
}
printf("End firmware update example, close socket\n");
/* stop SOEM, close socket */
@ -133,17 +224,20 @@ void boottest(char *ifname, uint16 slave, char *filename)
else
{
printf("No socket connection on %s\nExcecute as root\n",ifname);
retval = 1;
}
return retval;
}
int main(int argc, char *argv[])
{
int ret = 0;
printf("SOEM (Simple Open EtherCAT Master)\nFirmware update example\n");
if (argc > 3)
{
argslave = atoi(argv[2]);
boottest(argv[1], argslave, argv[3]);
ret = boottest(argv[1], argslave, argv[3]);
}
else
{
@ -155,5 +249,6 @@ int main(int argc, char *argv[])
}
printf("End program\n");
return (0);
return ret;
}