Update App to use new DC checks, set error function, SM watchdog, fixed EEPROM delayed write and move generic slave functionallity to generic SOES
parent
ca48f9db21
commit
6fb665a701
|
@ -26,7 +26,7 @@
|
|||
#define MBX1_smc_b 0x22
|
||||
|
||||
#define SM2_sma 0x1100
|
||||
#define SM2_smc 0x24
|
||||
#define SM2_smc 0x64
|
||||
#define SM2_act 1
|
||||
#define SM3_sma 0x1180
|
||||
#define SM3_smc 0x20
|
||||
|
|
|
@ -1,184 +1,96 @@
|
|||
|
||||
#include <cc.h>
|
||||
#include <kern.h>
|
||||
#include <xmc4.h>
|
||||
#include <bsp.h>
|
||||
#include "slave.h"
|
||||
#include "esc_hw.h"
|
||||
#include "esc.h"
|
||||
#include "ecat_slv.h"
|
||||
#include "config.h"
|
||||
|
||||
#define SAMPLE_CODE 0
|
||||
#include "utypes.h"
|
||||
|
||||
/**
|
||||
* This function reads physical input values and assigns the corresponding members
|
||||
* of Rb.Buttons
|
||||
* This function is called when to get input values
|
||||
*/
|
||||
void cb_get_Buttons()
|
||||
void cb_get_inputs()
|
||||
{
|
||||
Rb.Buttons.Button1 = gpio_get(GPIO_BUTTON1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function writes physical output values from the corresponding members of
|
||||
* Wb.LEDs
|
||||
* This function is called when to set outputs values
|
||||
*/
|
||||
void cb_set_LEDgroup0()
|
||||
void cb_set_outputs()
|
||||
{
|
||||
gpio_set(GPIO_LED1, Wb.LEDgroup0.LED0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function writes physical output values from the corresponding members of
|
||||
* Wb.LEDs
|
||||
*/
|
||||
void cb_set_LEDgroup1()
|
||||
{
|
||||
gpio_set(GPIO_LED2, Wb.LEDgroup1.LED1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called after a SDO write of the object Cb.Parameters.
|
||||
*/
|
||||
void cb_post_write_variableRW(int subindex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** Optional: Hook called after state change for application specific
|
||||
* actions for specific state changes.
|
||||
*/
|
||||
void pre_state_change_hook (uint8_t * as, uint8_t * an)
|
||||
{
|
||||
}
|
||||
|
||||
/** Optional: Hook called after state change for application specific
|
||||
* actions for specific state changes.
|
||||
*/
|
||||
void post_state_change_hook (uint8_t * as, uint8_t * an)
|
||||
{
|
||||
#if SAMPLE_CODE
|
||||
/* Add specific step change hooks here */
|
||||
if ((*as == BOOT_TO_INIT) && (*an == ESCinit))
|
||||
if ((*as == SAFEOP_TO_OP))
|
||||
{
|
||||
rprintf("boot BOOT_TO_INIT\n");
|
||||
upgrade_finished();
|
||||
/* If we return here */
|
||||
ESC_ALerror (ALERR_NOVALIDFIRMWARE);
|
||||
/* Upgrade failed, enter init with error */
|
||||
*an = (ESCinit | ESCerror);
|
||||
ESC_ALeventmaskwrite(ESC_ALeventmaskread() | ESCREG_ALEVENT_WD);
|
||||
}
|
||||
else if((*as == PREOP_TO_SAFEOP))
|
||||
{
|
||||
rprintf("boot PREOP_TO_SAFEOP\n");
|
||||
ESC_ALerror (ALERR_NOVALIDFIRMWARE);
|
||||
/* Stay in preop with error bit set */
|
||||
*an = (ESCpreop | ESCerror);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void user_post_dl_objecthandler (uint16_t index, uint8_t subindex)
|
||||
void safe_out(void)
|
||||
{
|
||||
#if SAMPLE_CODE
|
||||
switch (index)
|
||||
{
|
||||
case 0x1c12:
|
||||
{
|
||||
RXPDOsize = ESC_SM2_sml = sizeRXPDO();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle post-write of parameter values */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
rprintp("safe out\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int user_pre_dl_objecthandler (uint16_t index, uint8_t subindex)
|
||||
/* Setup of DC */
|
||||
uint16_t dc_checker(void)
|
||||
{
|
||||
#if SAMPLE_CODE
|
||||
if (index == 0x1c12)
|
||||
{
|
||||
SDO_abort (index, subindex, ABORT_READONLY);
|
||||
return 0;
|
||||
}
|
||||
if (index == 0x1c13)
|
||||
{
|
||||
SDO_abort (index, subindex, ABORT_READONLY);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Called from stack when stopping outputs */
|
||||
void user_safeoutput (void)
|
||||
{
|
||||
#if SAMPLE_CODE
|
||||
DPRINT ("APP_safeoutput\n");
|
||||
|
||||
// Set safe values for Wb.LEDgroup0
|
||||
Wb.LEDgroup0.LED0 = 1;
|
||||
|
||||
// Set safe values for Wb.LEDgroup1
|
||||
Wb.LEDgroup1.LED1 = 1;
|
||||
#endif
|
||||
/* Indicate we run DC */
|
||||
ESCvar.dcsync = 1;
|
||||
/* Fetch the sync counter limit SDO10F1*/
|
||||
ESCvar.synccounterlimit = Mb.ErrorSettings.SyncErrorCounterLimit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Configuration parameters for SOES
|
||||
* SM and Mailbox parameters comes from the
|
||||
* generated config.h
|
||||
*/
|
||||
static esc_cfg_t config =
|
||||
{
|
||||
.user_arg = NULL,
|
||||
.use_interrupt = 1,
|
||||
.watchdog_cnt = 100,
|
||||
.mbxsize = MBXSIZE,
|
||||
.mbxsizeboot = MBXSIZEBOOT,
|
||||
.mbxbuffers = MBXBUFFERS,
|
||||
.mb[0] = {MBX0_sma, MBX0_sml, MBX0_sme, MBX0_smc, 0},
|
||||
.mb[1] = {MBX1_sma, MBX1_sml, MBX1_sme, MBX1_smc, 0},
|
||||
.mb_boot[0] = {MBX0_sma_b, MBX0_sml_b, MBX0_sme_b, MBX0_smc_b, 0},
|
||||
.mb_boot[1] = {MBX1_sma_b, MBX1_sml_b, MBX1_sme_b, MBX1_smc_b, 0},
|
||||
.pdosm[0] = {SM2_sma, 0, 0, SM2_smc, SM2_act},
|
||||
.pdosm[1] = {SM3_sma, 0, 0, SM3_smc, SM3_act},
|
||||
.pre_state_change_hook = NULL,
|
||||
.post_state_change_hook = NULL,
|
||||
.application_hook = NULL,
|
||||
.safeoutput_override = user_safeoutput,
|
||||
.pre_object_download_hook = user_pre_dl_objecthandler,
|
||||
.post_object_download_hook = user_post_dl_objecthandler,
|
||||
.rxpdo_override = NULL,
|
||||
.txpdo_override = NULL,
|
||||
.esc_hw_interrupt_enable = ESC_interrupt_enable,
|
||||
.esc_hw_interrupt_disable = ESC_interrupt_disable,
|
||||
.esc_hw_eep_handler = ESC_eep_handler
|
||||
};
|
||||
|
||||
void main_run(void * arg)
|
||||
{
|
||||
ecat_slv_init(&config);
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(config.use_interrupt != 0)
|
||||
{
|
||||
DIG_process(DIG_PROCESS_WD_FLAG);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecat_slv();
|
||||
}
|
||||
task_delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rprintf("Hello Main\n");
|
||||
task_spawn ("soes", main_run, 8, 2048, NULL);
|
||||
esc_cfg_t config =
|
||||
{
|
||||
.user_arg = NULL,
|
||||
.use_interrupt = 1,
|
||||
.watchdog_cnt = INT32_MAX, /* Use HW SM watchdog instead */
|
||||
.mbxsize = MBXSIZE,
|
||||
.mbxsizeboot = MBXSIZEBOOT,
|
||||
.mbxbuffers = MBXBUFFERS,
|
||||
.rxpdosaddress = &Wb,
|
||||
.txpdosaddress = &Rb,
|
||||
.mb[0] = {MBX0_sma, MBX0_sml, MBX0_sme, MBX0_smc, 0},
|
||||
.mb[1] = {MBX1_sma, MBX1_sml, MBX1_sme, MBX1_smc, 0},
|
||||
.mb_boot[0] = {MBX0_sma_b, MBX0_sml_b, MBX0_sme_b, MBX0_smc_b, 0},
|
||||
.mb_boot[1] = {MBX1_sma_b, MBX1_sml_b, MBX1_sme_b, MBX1_smc_b, 0},
|
||||
.pdosm[0] = {SM2_sma, 0, 0, SM2_smc, SM2_act},
|
||||
.pdosm[1] = {SM3_sma, 0, 0, SM3_smc, SM3_act},
|
||||
.pre_state_change_hook = NULL,
|
||||
.post_state_change_hook = post_state_change_hook,
|
||||
.application_hook = NULL,
|
||||
.safeoutput_override = safe_out,
|
||||
.pre_object_download_hook = NULL,
|
||||
.post_object_download_hook = NULL,
|
||||
.rxpdo_override = NULL,
|
||||
.txpdo_override = NULL,
|
||||
.esc_hw_interrupt_enable = ESC_interrupt_enable,
|
||||
.esc_hw_interrupt_disable = ESC_interrupt_disable,
|
||||
.esc_hw_eep_handler = ESC_eep_handler,
|
||||
.esc_check_dc_handler = dc_checker
|
||||
};
|
||||
|
||||
rprintf("Hello Main\n");
|
||||
ecat_slv_init(&config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,11 +1,7 @@
|
|||
#ifndef SOES_V1
|
||||
#include <stddef.h>
|
||||
#include "utypes.h"
|
||||
#include "esc.h"
|
||||
#include "esc_coe.h"
|
||||
#include "esc_foe.h"
|
||||
#include "config.h"
|
||||
#include "slave.h"
|
||||
#include "esc.h"
|
||||
|
||||
/* Global variables used by the stack */
|
||||
uint8_t MBX[MBXBUFFERS * MAX(MBXSIZE,MBXSIZEBOOT)];
|
||||
|
@ -17,318 +13,3 @@ _Rbuffer Rb;
|
|||
_Wbuffer Wb;
|
||||
_Cbuffer Cb;
|
||||
_Mbuffer Mb;
|
||||
|
||||
/* Private variables */
|
||||
static volatile int watchdog;
|
||||
|
||||
/** Mandatory: Function to pre-qualify the incoming SDO download.
|
||||
*
|
||||
* @param[in] index = index of SDO download request to check
|
||||
* @param[in] sub-index = sub-index of SDO download request to check
|
||||
* @return 1 if the SDO Download is correct. 0 If not correct.
|
||||
*/
|
||||
int ESC_pre_objecthandler (uint16_t index, uint8_t subindex)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
if(ESCvar.pre_object_download_hook)
|
||||
{
|
||||
result = (ESCvar.pre_object_download_hook)(index, subindex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Mandatory: Hook called from the slave stack SDO Download handler to act on
|
||||
* user specified Index and Sub-index.
|
||||
*
|
||||
* @param[in] index = index of SDO download request to handle
|
||||
* @param[in] sub-index = sub-index of SDO download request to handle
|
||||
*/
|
||||
void ESC_objecthandler (uint16_t index, uint8_t subindex)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
/* Handle post-write of parameter values */
|
||||
case 0x8001:
|
||||
{
|
||||
cb_post_write_variableRW(subindex);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(ESCvar.post_object_download_hook != NULL)
|
||||
{
|
||||
(ESCvar.post_object_download_hook)(index, subindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Hook called from the slave stack ESC_stopoutputs to act on state changes
|
||||
* forcing us to stop outputs. Here we can set them to a safe state.
|
||||
* set
|
||||
*/
|
||||
void APP_safeoutput (void)
|
||||
{
|
||||
DPRINT ("APP_safeoutput\n");
|
||||
|
||||
if(ESCvar.safeoutput_override != NULL)
|
||||
{
|
||||
(ESCvar.safeoutput_override)();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set safe values for Wb.LEDgroup0
|
||||
Wb.LEDgroup0.LED0 = 0;
|
||||
// Set safe values for Wb.LEDgroup1
|
||||
Wb.LEDgroup1.LED1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Write local process data to Sync Manager 3, Master Inputs.
|
||||
*/
|
||||
void TXPDO_update (void)
|
||||
{
|
||||
if(ESCvar.txpdo_override != NULL)
|
||||
{
|
||||
(ESCvar.txpdo_override)();
|
||||
}
|
||||
else
|
||||
{
|
||||
ESC_write (SM3_sma, &Rb, ESCvar.TXPDOsize);
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Read Sync Manager 2 to local process data, Master Outputs.
|
||||
*/
|
||||
void RXPDO_update (void)
|
||||
{
|
||||
if(ESCvar.rxpdo_override != NULL)
|
||||
{
|
||||
(ESCvar.rxpdo_override)();
|
||||
}
|
||||
else
|
||||
{
|
||||
ESC_read (SM2_sma, &Wb, ESCvar.RXPDOsize);
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Function to update local I/O, call read ethercat outputs, call
|
||||
* write ethercat inputs. Implement watch-dog counter to count-out if we have
|
||||
* made state change affecting the App.state.
|
||||
*/
|
||||
void DIG_process (uint8_t flags)
|
||||
{
|
||||
/* Handle watchdog */
|
||||
if((flags & DIG_PROCESS_WD_FLAG) > 0)
|
||||
{
|
||||
|
||||
if (CC_ATOMIC_GET(watchdog) > 0)
|
||||
{
|
||||
CC_ATOMIC_SUB(watchdog, 1);
|
||||
}
|
||||
|
||||
if ((CC_ATOMIC_GET(watchdog) <= 0) &&
|
||||
((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0))
|
||||
{
|
||||
DPRINT("DIG_process watchdog expired\n");
|
||||
ESC_stopoutput();
|
||||
/* watchdog, invalid outputs */
|
||||
ESC_ALerror (ALERR_WATCHDOG);
|
||||
/* goto safe-op with error bit set */
|
||||
ESC_ALstatus (ESCsafeop | ESCerror);
|
||||
}
|
||||
else if(((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) == 0))
|
||||
{
|
||||
CC_ATOMIC_SET(watchdog, ESCvar.watchdogcnt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Outputs */
|
||||
if ((flags & DIG_PROCESS_OUTPUTS_FLAG) > 0)
|
||||
{
|
||||
if(((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0) &&
|
||||
(ESCvar.ALevent & ESCREG_ALEVENT_SM2))
|
||||
{
|
||||
RXPDO_update();
|
||||
CC_ATOMIC_SET(watchdog, ESCvar.watchdogcnt);
|
||||
if(ESCvar.dcsync > 0)
|
||||
{
|
||||
CC_ATOMIC_ADD(ESCvar.synccounter, 1);
|
||||
}
|
||||
/* Set outputs */
|
||||
cb_set_LEDgroup0();
|
||||
cb_set_LEDgroup1();
|
||||
}
|
||||
else if (ESCvar.ALevent & ESCREG_ALEVENT_SM2)
|
||||
{
|
||||
RXPDO_update();
|
||||
}
|
||||
}
|
||||
|
||||
/* Call application */
|
||||
if ((flags & DIG_PROCESS_APP_HOOK_FLAG) > 0)
|
||||
{
|
||||
|
||||
if((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0)
|
||||
{
|
||||
CC_ATOMIC_SUB(ESCvar.synccounter, 1);
|
||||
}
|
||||
|
||||
if((ESCvar.dcsync > 0) &&
|
||||
((CC_ATOMIC_GET(ESCvar.synccounter) < -ESCvar.synccounterlimit) ||
|
||||
(CC_ATOMIC_GET(ESCvar.synccounter) > ESCvar.synccounterlimit)))
|
||||
{
|
||||
if((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0)
|
||||
{
|
||||
DPRINT("sync error = %d\n", ESCvar.synccounter);
|
||||
ESC_stopoutput();
|
||||
/* Sync error */
|
||||
ESC_ALerror (ALERR_SYNCERROR);
|
||||
/* goto safe-op with error bit set */
|
||||
ESC_ALstatus (ESCsafeop | ESCerror);
|
||||
CC_ATOMIC_SET(ESCvar.synccounter, 0);
|
||||
}
|
||||
}
|
||||
/* Call application callback if set */
|
||||
if (ESCvar.application_hook != NULL)
|
||||
{
|
||||
(ESCvar.application_hook)();
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Inputs */
|
||||
if ((flags & DIG_PROCESS_INPUTS_FLAG) > 0)
|
||||
{
|
||||
if(CC_ATOMIC_GET(ESCvar.App.state) > 0)
|
||||
{
|
||||
/* Update inputs */
|
||||
cb_get_Buttons();
|
||||
TXPDO_update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for SM change, SM0/1, AL CONTROL and EEPROM events, the application
|
||||
* control what interrupts that should be served and re-activated with
|
||||
* event mask argument
|
||||
*/
|
||||
void ecat_slv_worker (uint32_t event_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Check the state machine */
|
||||
ESC_state();
|
||||
/* Check the SM activation event */
|
||||
ESC_sm_act_event();
|
||||
|
||||
/* Check mailboxes */
|
||||
while ((ESC_mbxprocess() > 0) || (ESCvar.txcue > 0))
|
||||
{
|
||||
ESC_coeprocess();
|
||||
ESC_foeprocess();
|
||||
ESC_xoeprocess();
|
||||
}
|
||||
|
||||
/* Call emulated eeprom handler if set */
|
||||
if (ESCvar.esc_hw_eep_handler != NULL)
|
||||
{
|
||||
(ESCvar.esc_hw_eep_handler)();
|
||||
}
|
||||
|
||||
CC_ATOMIC_SET(ESCvar.ALevent, ESC_ALeventread());
|
||||
|
||||
}while(ESCvar.ALevent & event_mask);
|
||||
|
||||
ESC_ALeventmaskwrite(ESC_ALeventmaskread() | event_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* ISR function. It should be called from ISR for applications entirely driven by
|
||||
* interrupts.
|
||||
* Read and handle events for the EtherCAT state, status, mailbox and eeprom.
|
||||
*/
|
||||
void ecat_slv_isr (void)
|
||||
{
|
||||
ecat_slv_worker(ESCREG_ALEVENT_CONTROL | ESCREG_ALEVENT_SMCHANGE
|
||||
| ESCREG_ALEVENT_SM0 | ESCREG_ALEVENT_SM1 | ESCREG_ALEVENT_EEP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Polling function. It should be called periodically for an application
|
||||
* when only SM2/DC interrupt is active.
|
||||
* Read and handle events for the EtherCAT state, status, mailbox and eeprom.
|
||||
*/
|
||||
void ecat_slv_poll (void)
|
||||
{
|
||||
/* Read local time from ESC*/
|
||||
ESC_read (ESCREG_LOCALTIME, (void *) &ESCvar.Time, sizeof (ESCvar.Time));
|
||||
ESCvar.Time = etohl (ESCvar.Time);
|
||||
|
||||
/* Check the state machine */
|
||||
ESC_state();
|
||||
/* Check the SM activation event */
|
||||
ESC_sm_act_event();
|
||||
|
||||
/* Check mailboxes */
|
||||
if (ESC_mbxprocess())
|
||||
{
|
||||
ESC_coeprocess();
|
||||
ESC_foeprocess();
|
||||
ESC_xoeprocess();
|
||||
}
|
||||
|
||||
/* Call emulated eeprom handler if set */
|
||||
if (ESCvar.esc_hw_eep_handler != NULL)
|
||||
{
|
||||
(ESCvar.esc_hw_eep_handler)();
|
||||
}
|
||||
}
|
||||
|
||||
void ecat_slv (void)
|
||||
{
|
||||
ecat_slv_poll();
|
||||
DIG_process(DIG_PROCESS_WD_FLAG | DIG_PROCESS_OUTPUTS_FLAG |
|
||||
DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the slave stack.
|
||||
*/
|
||||
void ecat_slv_init (esc_cfg_t * config)
|
||||
{
|
||||
DPRINT ("Slave stack init started\n");
|
||||
|
||||
ESCvar.TXPDOsize = ESCvar.ESC_SM3_sml = sizeOfPDO(TX_PDO_OBJIDX);
|
||||
ESCvar.RXPDOsize = ESCvar.ESC_SM2_sml = sizeOfPDO(RX_PDO_OBJIDX);
|
||||
|
||||
/* Init watchdog */
|
||||
watchdog = config->watchdog_cnt;
|
||||
|
||||
/* Call stack configuration */
|
||||
ESC_config (config);
|
||||
/* Call HW init */
|
||||
ESC_init (config);
|
||||
|
||||
/* wait until ESC is started up */
|
||||
while ((ESCvar.DLstatus & 0x0001) == 0)
|
||||
{
|
||||
ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,
|
||||
sizeof (ESCvar.DLstatus));
|
||||
ESCvar.DLstatus = etohs (ESCvar.DLstatus);
|
||||
}
|
||||
|
||||
/* Init FoE */
|
||||
FOE_init();
|
||||
|
||||
/* reset ESC to init state */
|
||||
ESC_ALstatus (ESCinit);
|
||||
ESC_ALerror (ALERR_NONE);
|
||||
ESC_stopmbx();
|
||||
ESC_stopinput();
|
||||
ESC_stopoutput();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Slave fileVersion="1" id="xmc43_slave" productCode="4300">
|
||||
<Slave fileVersion="1" id="xmc43_slave" productCode="0x4300">
|
||||
<Name>xmc43relax</Name>
|
||||
<Vendor>
|
||||
<Id>0x1337</Id>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<Fmmu>MBoxState</Fmmu>
|
||||
<Sm ControlByte="0x26" DefaultSize="128" StartAddress="0x1000">MBoxOut</Sm>
|
||||
<Sm ControlByte="0x22" DefaultSize="128" StartAddress="0x1080">MBoxIn</Sm>
|
||||
<Sm ControlByte="0x24" DefaultSize="0" StartAddress="0x1100">Outputs</Sm>
|
||||
<Sm ControlByte="0x64" DefaultSize="0" StartAddress="0x1100">Outputs</Sm>
|
||||
<Sm ControlByte="0x20" DefaultSize="0" StartAddress="0x1180">Inputs</Sm>
|
||||
<Mailbox CoE="true" FoE="true">
|
||||
<Bootstrap Length="256" Start="0x1000"/>
|
||||
|
@ -69,7 +69,7 @@
|
|||
<Name>Product Code</Name>
|
||||
<Index>0x02</Index>
|
||||
<DataType>UNSIGNED32</DataType>
|
||||
<DefaultValue>4300</DefaultValue>
|
||||
<DefaultValue>0x4300</DefaultValue>
|
||||
</SubItem>
|
||||
<SubItem>
|
||||
<Name>Revision Number</Name>
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
</Groups>
|
||||
<Devices>
|
||||
<Device Physics="YY">
|
||||
<Type ProductCode="4300" RevisionNo="0">xmc43_slave</Type>
|
||||
<Type ProductCode="#x4300" RevisionNo="0">xmc43_slave</Type>
|
||||
<Name LcId="1033">xmc43relax</Name>
|
||||
<GroupType>xmc4</GroupType>
|
||||
<Profile>
|
||||
<ProfileNo>5001</ProfileNo>
|
||||
<AddInfo>400</AddInfo>
|
||||
<AddInfo>0</AddInfo>
|
||||
<Dictionary>
|
||||
<DataTypes>
|
||||
<DataType>
|
||||
|
@ -680,7 +680,7 @@
|
|||
<SubItem>
|
||||
<Name>Product Code</Name>
|
||||
<Info>
|
||||
<DefaultValue>4300</DefaultValue>
|
||||
<DefaultValue>#x4300</DefaultValue>
|
||||
</Info>
|
||||
</SubItem>
|
||||
<SubItem>
|
||||
|
@ -1140,7 +1140,7 @@
|
|||
<Fmmu>MBoxState</Fmmu>
|
||||
<Sm ControlByte="#x26" DefaultSize="128" Enable="1" StartAddress="#x1000">MBoxOut</Sm>
|
||||
<Sm ControlByte="#x22" DefaultSize="128" Enable="1" StartAddress="#x1080">MBoxIn</Sm>
|
||||
<Sm ControlByte="#x24" Enable="1" StartAddress="#x1100">Outputs</Sm>
|
||||
<Sm ControlByte="#x64" Enable="1" StartAddress="#x1100">Outputs</Sm>
|
||||
<Sm ControlByte="#x20" Enable="1" StartAddress="#x1180">Inputs</Sm>
|
||||
<RxPdo Fixed="true" Mandatory="true" Sm="2">
|
||||
<Index>#x1600</Index>
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
#include "utypes.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef HW_REV
|
||||
#define HW_REV "1.0"
|
||||
#endif
|
||||
|
||||
#ifndef SW_REV
|
||||
#define SW_REV "1.0"
|
||||
#endif
|
||||
|
||||
static const char acName1000[] = "Device Type";
|
||||
static const char acName1000_0[] = "Device Type";
|
||||
static const char acName1008[] = "Device Name";
|
||||
|
@ -90,17 +98,17 @@ const _objd SDO1008[] =
|
|||
};
|
||||
const _objd SDO1009[] =
|
||||
{
|
||||
{0x0, DTYPE_VISIBLE_STRING, 24, ATYPE_RO, acName1009_0, 0, "1.0"},
|
||||
{0x0, DTYPE_VISIBLE_STRING, 24, ATYPE_RO, acName1009_0, 0, HW_REV},
|
||||
};
|
||||
const _objd SDO100A[] =
|
||||
{
|
||||
{0x0, DTYPE_VISIBLE_STRING, 24, ATYPE_RO, acName100A_0, 0, "1.0"},
|
||||
{0x0, DTYPE_VISIBLE_STRING, 24, ATYPE_RO, acName100A_0, 0, SW_REV},
|
||||
};
|
||||
const _objd SDO1018[] =
|
||||
{
|
||||
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1018_00, 4, NULL},
|
||||
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_01, 0x1337, NULL},
|
||||
{0x02, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_02, 4300, NULL},
|
||||
{0x02, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_02, 0x4300, NULL},
|
||||
{0x03, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_03, 0, NULL},
|
||||
{0x04, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_04, 0x00000000, NULL},
|
||||
};
|
||||
|
@ -215,4 +223,4 @@ const _objectlist SDOobjects[] =
|
|||
{0x8001, OTYPE_VAR, 0, 0, acName8001, SDO8001},
|
||||
{0xffff, 0xff, 0xff, 0xff, NULL, NULL}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
|
||||
#ifndef SOES_V1
|
||||
#include <stddef.h>
|
||||
#include "esc.h"
|
||||
#include "esc_coe.h"
|
||||
#include "esc_foe.h"
|
||||
#include "ecat_slv.h"
|
||||
|
||||
/* Global variables used by the stack */
|
||||
extern _ESCvar ESCvar;
|
||||
|
||||
/* Private variables */
|
||||
static volatile int watchdog;
|
||||
|
||||
/** Mandatory: Function to pre-qualify the incoming SDO download.
|
||||
*
|
||||
* @param[in] index = index of SDO download request to check
|
||||
* @param[in] sub-index = sub-index of SDO download request to check
|
||||
* @return 1 if the SDO Download is correct. 0 If not correct.
|
||||
*/
|
||||
int ESC_pre_objecthandler (uint16_t index,
|
||||
uint8_t subindex,
|
||||
void * data,
|
||||
size_t size,
|
||||
bool isCA)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
if(ESCvar.pre_object_download_hook)
|
||||
{
|
||||
result = (ESCvar.pre_object_download_hook)(index,
|
||||
subindex,
|
||||
data,
|
||||
size,
|
||||
isCA);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Mandatory: Hook called from the slave stack SDO Download handler to act on
|
||||
* user specified Index and Sub-index.
|
||||
*
|
||||
* @param[in] index = index of SDO download request to handle
|
||||
* @param[in] sub-index = sub-index of SDO download request to handle
|
||||
*/
|
||||
void ESC_objecthandler (uint16_t index, uint8_t subindex, bool isCA)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
|
||||
default:
|
||||
{
|
||||
if ((index >= 0x1600 && index < 0x1800) || index == RX_PDO_OBJIDX)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if ((index >= 0x1A00 && index < 0x1C00) || index == TX_PDO_OBJIDX)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if(ESCvar.post_object_download_hook != NULL)
|
||||
{
|
||||
(ESCvar.post_object_download_hook)(index, subindex, isCA);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Hook called from the slave stack ESC_stopoutputs to act on state changes
|
||||
* forcing us to stop outputs. Here we can set them to a safe state.
|
||||
* set
|
||||
*/
|
||||
void APP_safeoutput (void)
|
||||
{
|
||||
DPRINT ("APP_safeoutput\n");
|
||||
|
||||
if(ESCvar.safeoutput_override != NULL)
|
||||
{
|
||||
(ESCvar.safeoutput_override)();
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Write local process data to Sync Manager 3, Master Inputs.
|
||||
*/
|
||||
void TXPDO_update (void)
|
||||
{
|
||||
if(ESCvar.txpdo_override != NULL)
|
||||
{
|
||||
(ESCvar.txpdo_override)();
|
||||
}
|
||||
else
|
||||
{
|
||||
ESC_write (ESC_SM3_sma, ESCvar.txpdosaddress , ESCvar.ESC_SM3_sml);
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Read Sync Manager 2 to local process data, Master Outputs.
|
||||
*/
|
||||
void RXPDO_update (void)
|
||||
{
|
||||
if(ESCvar.rxpdo_override != NULL)
|
||||
{
|
||||
(ESCvar.rxpdo_override)();
|
||||
}
|
||||
else
|
||||
{
|
||||
ESC_read (ESC_SM2_sma, ESCvar.rxpdosaddress, ESCvar.ESC_SM2_sml);
|
||||
}
|
||||
}
|
||||
|
||||
/** Mandatory: Function to update local I/O, call read ethercat outputs, call
|
||||
* write ethercat inputs. Implement watch-dog counter to count-out if we have
|
||||
* made state change affecting the App.state.
|
||||
*/
|
||||
void DIG_process (uint8_t flags)
|
||||
{
|
||||
/* Handle watchdog */
|
||||
if((flags & DIG_PROCESS_WD_FLAG) > 0)
|
||||
{
|
||||
if (CC_ATOMIC_GET(watchdog) > 0)
|
||||
{
|
||||
CC_ATOMIC_SUB(watchdog, 1);
|
||||
}
|
||||
|
||||
if ((CC_ATOMIC_GET(watchdog) <= 0) &&
|
||||
((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0))
|
||||
{
|
||||
DPRINT("DIG_process watchdog expired\n");
|
||||
ESC_ALstatusgotoerror((ESCsafeop | ESCerror), ALERR_WATCHDOG);
|
||||
}
|
||||
else if(((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) == 0))
|
||||
{
|
||||
CC_ATOMIC_SET(watchdog, ESCvar.watchdogcnt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Outputs */
|
||||
if ((flags & DIG_PROCESS_OUTPUTS_FLAG) > 0)
|
||||
{
|
||||
if(((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0) &&
|
||||
(ESCvar.ALevent & ESCREG_ALEVENT_SM2))
|
||||
{
|
||||
RXPDO_update();
|
||||
CC_ATOMIC_SET(watchdog, ESCvar.watchdogcnt);
|
||||
/* Set outputs */
|
||||
cb_set_outputs();
|
||||
}
|
||||
else if (ESCvar.ALevent & ESCREG_ALEVENT_SM2)
|
||||
{
|
||||
RXPDO_update();
|
||||
}
|
||||
}
|
||||
|
||||
/* Call application */
|
||||
if ((flags & DIG_PROCESS_APP_HOOK_FLAG) > 0)
|
||||
{
|
||||
/* Call application callback if set */
|
||||
if (ESCvar.application_hook != NULL)
|
||||
{
|
||||
(ESCvar.application_hook)();
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Inputs */
|
||||
if ((flags & DIG_PROCESS_INPUTS_FLAG) > 0)
|
||||
{
|
||||
if(CC_ATOMIC_GET(ESCvar.App.state) > 0)
|
||||
{
|
||||
/* Update inputs */
|
||||
cb_get_inputs();
|
||||
TXPDO_update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for SM change, SM0/1, AL CONTROL and EEPROM events, the application
|
||||
* control what interrupts that should be served and re-activated with
|
||||
* event mask argument
|
||||
*/
|
||||
void ecat_slv_worker (uint32_t event_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Check the state machine */
|
||||
ESC_state();
|
||||
/* Check the SM activation event */
|
||||
ESC_sm_act_event();
|
||||
|
||||
/* Check mailboxes */
|
||||
while ((ESC_mbxprocess() > 0) || (ESCvar.txcue > 0))
|
||||
{
|
||||
ESC_coeprocess();
|
||||
ESC_foeprocess();
|
||||
ESC_xoeprocess();
|
||||
}
|
||||
|
||||
/* Call emulated eeprom handler if set */
|
||||
if (ESCvar.esc_hw_eep_handler != NULL)
|
||||
{
|
||||
(ESCvar.esc_hw_eep_handler)();
|
||||
}
|
||||
|
||||
CC_ATOMIC_SET(ESCvar.ALevent, ESC_ALeventread());
|
||||
|
||||
}while(ESCvar.ALevent & event_mask);
|
||||
|
||||
ESC_ALeventmaskwrite(ESC_ALeventmaskread() | event_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Polling function. It should be called periodically for an application
|
||||
* when only SM2/DC interrupt is active.
|
||||
* Read and handle events for the EtherCAT state, status, mailbox and eeprom.
|
||||
*/
|
||||
void ecat_slv_poll (void)
|
||||
{
|
||||
/* Read local time from ESC*/
|
||||
ESC_read (ESCREG_LOCALTIME, (void *) &ESCvar.Time, sizeof (ESCvar.Time));
|
||||
ESCvar.Time = etohl (ESCvar.Time);
|
||||
|
||||
/* Check the state machine */
|
||||
ESC_state();
|
||||
/* Check the SM activation event */
|
||||
ESC_sm_act_event();
|
||||
|
||||
/* Check mailboxes */
|
||||
if (ESC_mbxprocess())
|
||||
{
|
||||
ESC_coeprocess();
|
||||
ESC_foeprocess();
|
||||
ESC_xoeprocess();
|
||||
}
|
||||
|
||||
/* Call emulated eeprom handler if set */
|
||||
if (ESCvar.esc_hw_eep_handler != NULL)
|
||||
{
|
||||
(ESCvar.esc_hw_eep_handler)();
|
||||
}
|
||||
}
|
||||
|
||||
void ecat_slv (void)
|
||||
{
|
||||
ecat_slv_poll();
|
||||
DIG_process(DIG_PROCESS_WD_FLAG | DIG_PROCESS_OUTPUTS_FLAG |
|
||||
DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the slave stack.
|
||||
*/
|
||||
void ecat_slv_init (esc_cfg_t * config)
|
||||
{
|
||||
DPRINT ("Slave stack init started\n");
|
||||
|
||||
ESCvar.ESC_SM3_sml = sizeOfPDO(TX_PDO_OBJIDX);
|
||||
ESCvar.ESC_SM2_sml = sizeOfPDO(RX_PDO_OBJIDX);
|
||||
|
||||
/* Init watchdog */
|
||||
watchdog = config->watchdog_cnt;
|
||||
|
||||
/* Call stack configuration */
|
||||
ESC_config (config);
|
||||
/* Call HW init */
|
||||
ESC_init (config);
|
||||
|
||||
/* wait until ESC is started up */
|
||||
while ((ESCvar.DLstatus & 0x0001) == 0)
|
||||
{
|
||||
ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,
|
||||
sizeof (ESCvar.DLstatus));
|
||||
ESCvar.DLstatus = etohs (ESCvar.DLstatus);
|
||||
}
|
||||
|
||||
/* Init FoE */
|
||||
FOE_init();
|
||||
|
||||
/* reset ESC to init state */
|
||||
ESC_ALstatus (ESCinit);
|
||||
ESC_ALerror (ALERR_NONE);
|
||||
ESC_stopmbx();
|
||||
ESC_stopinput();
|
||||
ESC_stopoutput();
|
||||
}
|
||||
#endif
|
|
@ -1,28 +1,17 @@
|
|||
#ifndef __SLAVE_H__
|
||||
#define __SLAVE_H__
|
||||
#ifndef __ECAT_SLV_H__
|
||||
#define __ECAT_SLV_H__
|
||||
|
||||
#include "utypes.h"
|
||||
#include "esc.h"
|
||||
|
||||
/**
|
||||
* This function gets input values and updates Rb.Buttons
|
||||
* This function is called when to get input values
|
||||
*/
|
||||
void cb_get_Buttons();
|
||||
void cb_get_inputs();
|
||||
|
||||
/**
|
||||
* This function sets output values according to Wb.LEDgroup0
|
||||
* This function is called when to set outputs values
|
||||
*/
|
||||
void cb_set_LEDgroup0();
|
||||
|
||||
/**
|
||||
* This function sets output values according to Wb.LEDgroup1
|
||||
*/
|
||||
void cb_set_LEDgroup1();
|
||||
|
||||
/**
|
||||
* This function is called after a SDO write of the object Cb.variableRW.
|
||||
*/
|
||||
void cb_post_write_variableRW(int subindex);
|
||||
void cb_set_outputs();
|
||||
|
||||
#define DIG_PROCESS_INPUTS_FLAG 0x01
|
||||
#define DIG_PROCESS_OUTPUTS_FLAG 0x02
|
||||
|
@ -47,12 +36,6 @@ void DIG_process (uint8_t flags);
|
|||
*/
|
||||
void ecat_slv_worker (uint32_t event_mask);
|
||||
|
||||
/**
|
||||
* ISR for SM0/1, EEPROM and AL CONTROL events in a SM/DC
|
||||
* synchronization application
|
||||
*/
|
||||
CC_DEPRECATED void ecat_slv_isr (void);
|
||||
|
||||
/**
|
||||
* Poll SM0/1, EEPROM and AL CONTROL events in a SM/DC synchronization
|
||||
* application
|
||||
|
@ -71,4 +54,4 @@ void ecat_slv (void);
|
|||
*/
|
||||
void ecat_slv_init (esc_cfg_t * config);
|
||||
|
||||
#endif /* __SLAVE_H__ */
|
||||
#endif /* __ECAT_SLV_H__ */
|
|
@ -1135,6 +1135,9 @@ void ESC_config (esc_cfg_t * cfg)
|
|||
ESCvar.mbxsizeboot = cfg->mbxsizeboot;
|
||||
ESCvar.mbxbuffers = cfg->mbxbuffers;
|
||||
|
||||
ESCvar.rxpdosaddress = cfg->rxpdosaddress;
|
||||
ESCvar.txpdosaddress = cfg->txpdosaddress;
|
||||
|
||||
ESCvar.mb[0] = cfg->mb[0];
|
||||
ESCvar.mb[1] = cfg->mb[1];
|
||||
ESCvar.mbboot[0] = cfg->mb_boot[0];
|
||||
|
|
26
soes/esc.h
26
soes/esc.h
|
@ -237,6 +237,8 @@ typedef struct esc_cfg
|
|||
size_t mbxsize;
|
||||
size_t mbxsizeboot;
|
||||
int mbxbuffers;
|
||||
void * rxpdosaddress;
|
||||
void * txpdosaddress;
|
||||
sm_cfg_t mb[2];
|
||||
sm_cfg_t mb_boot[2];
|
||||
sm_cfg_t pdosm[2];
|
||||
|
@ -244,8 +246,14 @@ typedef struct esc_cfg
|
|||
void (*post_state_change_hook) (uint8_t * as, uint8_t * an);
|
||||
void (*application_hook) (void);
|
||||
void (*safeoutput_override) (void);
|
||||
int (*pre_object_download_hook) (uint16_t index, uint8_t subindex);
|
||||
void (*post_object_download_hook) (uint16_t index, uint8_t subindex);
|
||||
int (*pre_object_download_hook) (uint16_t index,
|
||||
uint8_t subindex,
|
||||
void * data,
|
||||
size_t size,
|
||||
uint16_t flags);
|
||||
void (*post_object_download_hook) (uint16_t index,
|
||||
uint8_t subindex,
|
||||
uint16_t flags);
|
||||
void (*rxpdo_override) (void);
|
||||
void (*txpdo_override) (void);
|
||||
void (*esc_hw_interrupt_enable) (uint32_t mask);
|
||||
|
@ -349,6 +357,8 @@ typedef struct
|
|||
size_t mbxsize;
|
||||
size_t mbxsizeboot;
|
||||
int mbxbuffers;
|
||||
void * rxpdosaddress;
|
||||
void * txpdosaddress;
|
||||
sm_cfg_t mb[2];
|
||||
sm_cfg_t mbboot[2];
|
||||
sm_cfg_t pdosm[2];
|
||||
|
@ -356,8 +366,14 @@ typedef struct
|
|||
void (*post_state_change_hook) (uint8_t * as, uint8_t * an);
|
||||
void (*application_hook) (void);
|
||||
void (*safeoutput_override) (void);
|
||||
int (*pre_object_download_hook) (uint16_t index, uint8_t subindex);
|
||||
void (*post_object_download_hook) (uint16_t index, uint8_t subindex);
|
||||
int (*pre_object_download_hook) (uint16_t index,
|
||||
uint8_t subindex,
|
||||
void * data,
|
||||
size_t size,
|
||||
uint16_t flags);
|
||||
void (*post_object_download_hook) (uint16_t index,
|
||||
uint8_t subindex,
|
||||
uint16_t flags);
|
||||
void (*rxpdo_override) (void);
|
||||
void (*txpdo_override) (void);
|
||||
void (*esc_hw_interrupt_enable) (uint32_t mask);
|
||||
|
@ -370,8 +386,6 @@ typedef struct
|
|||
sm_cfg_t * activemb1;
|
||||
uint16_t ESC_SM2_sml;
|
||||
uint16_t ESC_SM3_sml;
|
||||
uint16_t TXPDOsize;
|
||||
uint16_t RXPDOsize;
|
||||
uint8_t dcsync;
|
||||
uint16_t synccounterlimit;
|
||||
uint16_t ALstatus;
|
||||
|
|
|
@ -414,14 +414,18 @@ void SDO_download (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* normal upload */
|
||||
/* normal download */
|
||||
size = (etohl (coesdo->size) & 0xffff);
|
||||
mbxdata = (&(coesdo->size)) + 1;
|
||||
}
|
||||
actsize = ((objd + nsub)->bitlength + 7) >> 3;
|
||||
if (actsize == size)
|
||||
{
|
||||
if (ESC_pre_objecthandler (index, subindex))
|
||||
if (ESC_pre_objecthandler (index,
|
||||
subindex,
|
||||
mbxdata,
|
||||
size,
|
||||
false))
|
||||
{
|
||||
copy2mbx (mbxdata, (objd + nsub)->data, size);
|
||||
MBXout = ESC_claimbuffer ();
|
||||
|
@ -439,7 +443,7 @@ void SDO_download (void)
|
|||
MBXcontrol[MBXout].state = MBXstate_outreq;
|
||||
}
|
||||
/* external object write handler */
|
||||
ESC_objecthandler (index, subindex);
|
||||
ESC_objecthandler (index, subindex, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -21,7 +21,7 @@ typedef struct CC_PACKED
|
|||
uint16_t bitlength;
|
||||
uint16_t access;
|
||||
const char *name;
|
||||
uint32_t value;
|
||||
uint64_t value;
|
||||
void *data;
|
||||
} _objd;
|
||||
CC_PACKED_END
|
||||
|
@ -88,9 +88,12 @@ void ESC_coeprocess (void);
|
|||
uint16_t sizeOfPDO (uint16_t index);
|
||||
void SDO_abort (uint16_t index, uint8_t subindex, uint32_t abortcode);
|
||||
void COE_initDefaultSyncMgrPara (void);
|
||||
|
||||
extern void ESC_objecthandler (uint16_t index, uint8_t subindex);
|
||||
extern int ESC_pre_objecthandler (uint16_t index, uint8_t subindex);
|
||||
extern void ESC_objecthandler (uint16_t index, uint8_t subindex, bool isCA);
|
||||
extern int ESC_pre_objecthandler (uint16_t index,
|
||||
uint8_t subindex,
|
||||
void * data,
|
||||
size_t size,
|
||||
bool isCA);
|
||||
extern const _objectlist SDOobjects[];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
#include <eru.h>
|
||||
#include <string.h>
|
||||
#include "esc_hw.h"
|
||||
#include "slave.h"
|
||||
#include "esc_eep.h"
|
||||
|
||||
#include "ecat_slv.h"
|
||||
#include "esc_hw_eep.h"
|
||||
|
||||
#define ESCADDR(x) (((uint8_t *) ECAT0_BASE) + x)
|
||||
|
||||
|
@ -175,7 +175,6 @@ void ESC_interrupt_disable (uint32_t mask)
|
|||
mask &= ~ESCREG_ALEVENT_DC_LATCH;
|
||||
UASSERT(0,EARG);
|
||||
}
|
||||
|
||||
ecat0->AL_EVENT_MASK &= ~mask;
|
||||
}
|
||||
|
||||
|
@ -193,6 +192,22 @@ void ESC_eep_handler(void)
|
|||
*/
|
||||
static void sync0_isr (void * arg)
|
||||
{
|
||||
/* Subtract the sync counter to check the pace compared to the SM IRQ */
|
||||
if((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0)
|
||||
{
|
||||
CC_ATOMIC_SUB(ESCvar.synccounter, 1);
|
||||
}
|
||||
/* Check so we're inside the limit */
|
||||
if((CC_ATOMIC_GET(ESCvar.synccounter) < -ESCvar.synccounterlimit) ||
|
||||
(CC_ATOMIC_GET(ESCvar.synccounter) > ESCvar.synccounterlimit))
|
||||
{
|
||||
if((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0)
|
||||
{
|
||||
DPRINT("sync error = %d\n", ESCvar.synccounter);
|
||||
ESC_ALstatusgotoerror((ESCsafeop | ESCerror), ALERR_SYNCERROR);
|
||||
CC_ATOMIC_SET(ESCvar.synccounter, 0);
|
||||
}
|
||||
}
|
||||
DIG_process(DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG);
|
||||
read_ack = ecat0->DC_SYNC0_STAT;
|
||||
}
|
||||
|
@ -203,13 +218,14 @@ static void sync0_isr (void * arg)
|
|||
*/
|
||||
static void ecat_isr (void * arg)
|
||||
{
|
||||
|
||||
ESC_read (ESCREG_LOCALTIME, (void *) &ESCvar.Time, sizeof (ESCvar.Time));
|
||||
ESCvar.Time = etohl (ESCvar.Time);
|
||||
CC_ATOMIC_SET(ESCvar.ALevent, etohl(ecat0->AL_EVENT_REQ));
|
||||
|
||||
/* Handle SM2 interrupt */
|
||||
if(ESCvar.ALevent & ESCREG_ALEVENT_SM2)
|
||||
{
|
||||
/* Is DC active or not */
|
||||
if(ESCvar.dcsync == 0)
|
||||
{
|
||||
DIG_process(DIG_PROCESS_OUTPUTS_FLAG | DIG_PROCESS_APP_HOOK_FLAG |
|
||||
|
@ -217,10 +233,16 @@ static void ecat_isr (void * arg)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Add the sync counter to check the pace compared to the SM IRQ */
|
||||
if((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0)
|
||||
{
|
||||
CC_ATOMIC_ADD(ESCvar.synccounter, 1);
|
||||
}
|
||||
DIG_process(DIG_PROCESS_OUTPUTS_FLAG);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle low prio interrupts */
|
||||
if(ESCvar.ALevent & (ESCREG_ALEVENT_CONTROL | ESCREG_ALEVENT_SMCHANGE
|
||||
| ESCREG_ALEVENT_SM0 | ESCREG_ALEVENT_SM1 | ESCREG_ALEVENT_EEP))
|
||||
{
|
||||
|
@ -229,16 +251,38 @@ static void ecat_isr (void * arg)
|
|||
| ESCREG_ALEVENT_SM0 | ESCREG_ALEVENT_SM1 | ESCREG_ALEVENT_EEP);
|
||||
sem_signal(ecat_isr_sem);
|
||||
}
|
||||
|
||||
/* SM watchdog */
|
||||
if(ESCvar.ALevent & ESCREG_ALEVENT_WD)
|
||||
{
|
||||
uint16_t wd;
|
||||
/* Ack the WD IRQ */
|
||||
wd = ecat0->WD_STAT_PDATA;
|
||||
/* Check if the WD have expired and if we're in OP */
|
||||
if(((wd & 0x1) == 0) &&
|
||||
((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0))
|
||||
{
|
||||
ESC_ALstatusgotoerror((ESCsafeop | ESCerror), ALERR_WATCHDOG);
|
||||
ecat0->AL_EVENT_MASK &= ~ESCREG_ALEVENT_WD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function for PDI ISR serving task */
|
||||
/* Function for low prio PDI interrupts and flushing of EEPROM RAM buffer
|
||||
* to flash.
|
||||
*/
|
||||
static void isr_run(void * arg)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
sem_wait(ecat_isr_sem);
|
||||
ecat_slv_worker(ESCREG_ALEVENT_CONTROL | ESCREG_ALEVENT_SMCHANGE
|
||||
| ESCREG_ALEVENT_SM0 | ESCREG_ALEVENT_SM1 | ESCREG_ALEVENT_EEP);
|
||||
/* Do while to handle write of eeprom, the write to flash is delayed */
|
||||
do
|
||||
{
|
||||
ecat_slv_worker(ESCREG_ALEVENT_CONTROL | ESCREG_ALEVENT_SMCHANGE
|
||||
| ESCREG_ALEVENT_SM0 | ESCREG_ALEVENT_SM1 | ESCREG_ALEVENT_EEP);
|
||||
|
||||
}while(eep_write_pending);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ static eep_block_t *cleanup_unused_sect(eep_block_t *block);
|
|||
|
||||
static int32_t is_sector_empty(uint32_t *addr);
|
||||
|
||||
uint8_t eep_write_pending;
|
||||
|
||||
/** Initialize EEPROM emulation (load default data, validate checksums, ...).
|
||||
*
|
||||
|
@ -135,6 +136,7 @@ void EEP_hw_process (void)
|
|||
/* update block pointer and reset write state */
|
||||
eep_curr_block = eep_next_block;
|
||||
eep_next_block = NULL;
|
||||
eep_write_pending = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -204,6 +206,7 @@ int8_t EEP_write (uint32_t addr, uint8_t *data, uint16_t count)
|
|||
eep_buf_dirty = 1;
|
||||
eep_write_req = 0;
|
||||
eep_last_write = ESCvar.Time;
|
||||
eep_write_pending = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
/* idle timeout in ns before actual flash write will be issued */
|
||||
#define EEP_IDLE_TIMEOUT 100000000
|
||||
|
||||
|
||||
/* Pages per emulated EEPROM block */
|
||||
#define EEP_BYTES_PER_SECTOR XMC4_EEPROM_SECTOR_SIZE_BYTES
|
||||
#define EEP_BYTES_PER_PAGE XMC4_PAGE_SIZE_BYTES
|
||||
|
@ -39,6 +38,8 @@ typedef struct CC_PACKED
|
|||
/* eeprom size increments in steps of 0x80 bytes */
|
||||
#define EEP_EMU_BYTES (EEP_DATA_BYTES & ~0x7f)
|
||||
|
||||
extern uint8_t eep_write_pending;
|
||||
|
||||
/* block structure */
|
||||
typedef struct CC_PACKED
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue