diff --git a/applications/tiesc_k2gice/config.h b/applications/tiesc_k2gice/config.h new file mode 100644 index 0000000..8e3321d --- /dev/null +++ b/applications/tiesc_k2gice/config.h @@ -0,0 +1,35 @@ +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include + +#define MBXSIZE 128 +#define MBXSIZEBOOT 128 +#define MBXBUFFERS 3 + +#define MBX0_sma 0x1000 +#define MBX0_sml MBXSIZE +#define MBX0_sme MBX0_sma+MBX0_sml-1 +#define MBX0_smc 0x26 +#define MBX1_sma MBX0_sma+MBX0_sml +#define MBX1_sml MBXSIZE +#define MBX1_sme MBX1_sma+MBX1_sml-1 +#define MBX1_smc 0x22 + +#define MBX0_sma_b 0x1000 +#define MBX0_sml_b MBXSIZEBOOT +#define MBX0_sme_b MBX0_sma_b+MBX0_sml_b-1 +#define MBX0_smc_b 0x26 +#define MBX1_sma_b MBX0_sma_b+MBX0_sml_b +#define MBX1_sml_b MBXSIZEBOOT +#define MBX1_sme_b MBX1_sma_b+MBX1_sml_b-1 +#define MBX1_smc_b 0x22 + +#define SM2_sma 0x1100 +#define SM2_smc 0x24 +#define SM2_act 1 +#define SM3_sma 0x1180 +#define SM3_smc 0x20 +#define SM3_act 1 + +#endif /* __CONFIG_H__ */ diff --git a/applications/tiesc_k2gice/k2gice.bin b/applications/tiesc_k2gice/k2gice.bin new file mode 100644 index 0000000..1f43875 Binary files /dev/null and b/applications/tiesc_k2gice/k2gice.bin differ diff --git a/applications/tiesc_k2gice/k2gice.c b/applications/tiesc_k2gice/k2gice.c new file mode 100644 index 0000000..54db3c3 --- /dev/null +++ b/applications/tiesc_k2gice/k2gice.c @@ -0,0 +1,326 @@ +#ifndef SOES_V1 +#include +#include "utypes.h" +#include "esc.h" +#include "esc_coe.h" +#include "esc_foe.h" +#include "config.h" +#include "k2gice.h" + +/* Global variables used by the stack */ +uint8_t MBX[MBXBUFFERS * MAX(MBXSIZE,MBXSIZEBOOT)]; +_MBXcontrol MBXcontrol[MBXBUFFERS]; +_ESCvar ESCvar; + +/* Application variables */ +_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 */ + 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.LED + Wb.LED = 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_LED(); + } + 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_BUTTON(); + 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 diff --git a/applications/tiesc_k2gice/k2gice.esx b/applications/tiesc_k2gice/k2gice.esx new file mode 100644 index 0000000..e70830c --- /dev/null +++ b/applications/tiesc_k2gice/k2gice.esx @@ -0,0 +1,242 @@ + + + k2gice + + 0x1337 + rt-labs + + + k2gice_t + k2gice_n + + Outputs + Inputs + MBoxState + MBoxOut + MBoxIn + Outputs + Inputs + + + + + + 2048 + 800CE08800000000 + 0010800080108000 + + + + Device Type + 0x1000 + UNSIGNED32 + 0x00001389 + + + Device Name + 0x1008 + VISIBLE_STRING + k2gice + + + Hardware Version + 0x1009 + VISIBLE_STRING + 1.0 + + + Software Version + 0x100A + VISIBLE_STRING + 1.0 + + + Identity Object + 0x1018 + RECORD + + Max SubIndex + 0x00 + UNSIGNED8 + 4 + + + Vendor ID + 0x01 + UNSIGNED32 + 0x1337 + + + Product Code + 0x02 + UNSIGNED32 + 0x1234 + + + Revision Number + 0x03 + UNSIGNED32 + 0 + + + Serial Number + 0x04 + UNSIGNED32 + 0x00000000 + + + + LED + 0x1600 + RECORD + + Max SubIndex + 0x00 + UNSIGNED8 + 1 + + + LED + 0x01 + UNSIGNED32 + 0x70000020 + + + + BUTTON + 0x1A00 + RECORD + + Max SubIndex + 0x00 + UNSIGNED8 + 1 + + + BUTTON + 0x01 + UNSIGNED32 + 0x60000020 + + + + Sync Manager Communication Type + 0x1C00 + ARRAY + + Max SubIndex + 0x00 + UNSIGNED8 + 4 + + + Communications Type SM0 + 0x01 + UNSIGNED8 + 1 + + + Communications Type SM1 + 0x02 + UNSIGNED8 + 2 + + + Communications Type SM2 + 0x03 + UNSIGNED8 + 3 + + + Communications Type SM3 + 0x04 + UNSIGNED8 + 4 + + + + Sync Manager 2 PDO Assignment + 0x1C12 + ARRAY + + Max SubIndex + 0x00 + UNSIGNED8 + 1 + + + PDO Mapping + 0x01 + UNSIGNED16 + 0x1600 + + + + Sync Manager 3 PDO Assignment + 0x1C13 + ARRAY + + Max SubIndex + 0x00 + UNSIGNED8 + 1 + + + PDO Mapping + 0x01 + UNSIGNED16 + 0x1A00 + + + + BUTTON + 0x6000 + UNSIGNED32 + 0 + RO + BUTTON + Input + + + LED + 0x7000 + UNSIGNED32 + 0 + RO + LED + Output + + + + 0x1600 + LED + LED + + 0x7000 + 0 + LED + + + + 0x1A00 + BUTTON + BUTTON + + 0x6000 + 0 + BUTTON + + + + 0x6000 + BUTTON + UNSIGNED32 + VAR + + + 0x7000 + LED + UNSIGNED32 + VAR + + \ No newline at end of file diff --git a/applications/tiesc_k2gice/k2gice.h b/applications/tiesc_k2gice/k2gice.h new file mode 100644 index 0000000..1b41384 --- /dev/null +++ b/applications/tiesc_k2gice/k2gice.h @@ -0,0 +1,64 @@ +#ifndef __K2GICE_H__ +#define __K2GICE_H__ + +#include "utypes.h" +#include "esc.h" + +/** + * This function gets input values and updates Rb.BUTTON + */ +void cb_get_BUTTON(); + +/** + * This function sets output values according to Wb.LED + */ +void cb_set_LED(); + +#define DIG_PROCESS_INPUTS_FLAG 0x01 +#define DIG_PROCESS_OUTPUTS_FLAG 0x02 +#define DIG_PROCESS_WD_FLAG 0x04 +#define DIG_PROCESS_APP_HOOK_FLAG 0x08 +/** Implements the watch-dog counter to count if we should make a state change + * due to missing incoming SM2 events. Updates local I/O and run the application + * in the following order, call read EtherCAT outputs, execute user provided + * application hook and call write EtherCAT inputs. + * + * @param[in] flags = User input what to execute + */ +void DIG_process (uint8_t flags); + +/** + * 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 + * + * @param[in] event_mask = Event mask for interrupts to serve and re-activate + * after served + */ +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 + */ +void ecat_slv_poll (void); + +/** + * Poll all events in a free-run application + */ +void ecat_slv (void); + +/** + * Initialize the slave stack + * + * @param[in] config = User input how to configure the stack + */ +void ecat_slv_init (esc_cfg_t * config); + +#endif /* __K2GICE_H__ */ diff --git a/applications/tiesc_k2gice/k2gice.xml b/applications/tiesc_k2gice/k2gice.xml new file mode 100644 index 0000000..4746524 --- /dev/null +++ b/applications/tiesc_k2gice/k2gice.xml @@ -0,0 +1,535 @@ + + + + #x1337 + rt-labs + + + + + k2gice_t + k2gice_n + + + + + k2gice + k2gice + k2gice_t + + 5001 + 0 + + + + DT1018 + 144 + + 0 + Max SubIndex + USINT + 8 + 0 + + ro + + + + 1 + Vendor ID + UDINT + 32 + 16 + + ro + + + + 2 + Product Code + UDINT + 32 + 48 + + ro + + + + 3 + Revision Number + UDINT + 32 + 80 + + ro + + + + 4 + Serial Number + UDINT + 32 + 112 + + ro + + + + + DT1600 + 48 + + 0 + Max SubIndex + USINT + 8 + 0 + + ro + + + + 1 + LED + UDINT + 32 + 16 + + ro + + + + + DT1A00 + 48 + + 0 + Max SubIndex + USINT + 8 + 0 + + ro + + + + 1 + BUTTON + UDINT + 32 + 16 + + ro + + + + + DT1C00ARR + USINT + 32 + + 1 + 4 + + + + DT1C00 + 48 + + 0 + Max SubIndex + USINT + 8 + 0 + + ro + + + + Elements + DT1C00ARR + 32 + 16 + + ro + + + + + DT1C12ARR + UINT + 16 + + 1 + 1 + + + + DT1C12 + 32 + + 0 + Max SubIndex + USINT + 8 + 0 + + ro + + + + Elements + DT1C12ARR + 16 + 16 + + ro + + + + + DT1C13ARR + UINT + 16 + + 1 + 1 + + + + DT1C13 + 32 + + 0 + Max SubIndex + USINT + 8 + 0 + + ro + + + + Elements + DT1C13ARR + 16 + 16 + + ro + + + + + STRING(6) + 48 + + + STRING(3) + 24 + + + UDINT + 32 + + + UINT + 16 + + + USINT + 8 + + + + + #x1000 + Device Type + UDINT + 32 + + #x00001389 + + + ro + m + + + + #x1008 + Device Name + STRING(6) + 48 + + k2gice + + + ro + + + + #x1009 + Hardware Version + STRING(3) + 24 + + 1.0 + + + ro + o + + + + #x100A + Software Version + STRING(3) + 24 + + 1.0 + + + ro + + + + #x1018 + Identity Object + DT1018 + 144 + + + Max SubIndex + + 4 + + + + Vendor ID + + #x1337 + + + + Product Code + + #x1234 + + + + Revision Number + + 0 + + + + Serial Number + + #x00000000 + + + + + ro + + + + #x1600 + LED + DT1600 + 48 + + + Max SubIndex + + 1 + + + + LED + + #x70000020 + + + + + ro + + + + #x1A00 + BUTTON + DT1A00 + 48 + + + Max SubIndex + + 1 + + + + BUTTON + + #x60000020 + + + + + ro + + + + #x1C00 + Sync Manager Communication Type + DT1C00 + 48 + + + Max SubIndex + + 4 + + + + Communications Type SM0 + + 1 + + + + Communications Type SM1 + + 2 + + + + Communications Type SM2 + + 3 + + + + Communications Type SM3 + + 4 + + + + + ro + + + + #x1C12 + Sync Manager 2 PDO Assignment + DT1C12 + 32 + + + Max SubIndex + + 1 + + + + PDO Mapping + + #x1600 + + + + + ro + + + + #x1C13 + Sync Manager 3 PDO Assignment + DT1C13 + 32 + + + Max SubIndex + + 1 + + + + PDO Mapping + + #x1A00 + + + + + ro + + + + #x6000 + BUTTON + UDINT + 32 + + 0 + + + ro + + + + #x7000 + LED + UDINT + 32 + + 0 + + + ro + + + + + + Outputs + Inputs + MBoxState + MBoxOut + MBoxIn + Outputs + Inputs + + #x1600 + LED + + #x7000 + 0 + 32 + LED + UDINT + + + + #x1A00 + BUTTON + + #x6000 + 0 + 32 + BUTTON + UDINT + + + + + + + 2048 + 800CE08800000000 + 0010800080108000 + + + + + \ No newline at end of file diff --git a/applications/tiesc_k2gice/k2gice_objectlist.c b/applications/tiesc_k2gice/k2gice_objectlist.c new file mode 100644 index 0000000..46cb82b --- /dev/null +++ b/applications/tiesc_k2gice/k2gice_objectlist.c @@ -0,0 +1,128 @@ +#ifndef SOES_V1 +#include "esc_coe.h" +#include "utypes.h" +#include + +#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"; +static const char acName1008_0[] = "Device Name"; +static const char acName1009[] = "Hardware Version"; +static const char acName1009_0[] = "Hardware Version"; +static const char acName100A[] = "Software Version"; +static const char acName100A_0[] = "Software Version"; +static const char acName1018[] = "Identity Object"; +static const char acName1018_00[] = "Max SubIndex"; +static const char acName1018_01[] = "Vendor ID"; +static const char acName1018_02[] = "Product Code"; +static const char acName1018_03[] = "Revision Number"; +static const char acName1018_04[] = "Serial Number"; +static const char acName1600[] = "LED"; +static const char acName1600_00[] = "Max SubIndex"; +static const char acName1600_01[] = "LED"; +static const char acName1A00[] = "BUTTON"; +static const char acName1A00_00[] = "Max SubIndex"; +static const char acName1A00_01[] = "BUTTON"; +static const char acName1C00[] = "Sync Manager Communication Type"; +static const char acName1C00_00[] = "Max SubIndex"; +static const char acName1C00_01[] = "Communications Type SM0"; +static const char acName1C00_02[] = "Communications Type SM1"; +static const char acName1C00_03[] = "Communications Type SM2"; +static const char acName1C00_04[] = "Communications Type SM3"; +static const char acName1C12[] = "Sync Manager 2 PDO Assignment"; +static const char acName1C12_00[] = "Max SubIndex"; +static const char acName1C12_01[] = "PDO Mapping"; +static const char acName1C13[] = "Sync Manager 3 PDO Assignment"; +static const char acName1C13_00[] = "Max SubIndex"; +static const char acName1C13_01[] = "PDO Mapping"; +static const char acName6000[] = "BUTTON"; +static const char acName6000_0[] = "BUTTON"; +static const char acName7000[] = "LED"; +static const char acName7000_0[] = "LED"; + +const _objd SDO1000[] = +{ + {0x0, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1000_0, 0x00001389, NULL}, +}; +const _objd SDO1008[] = +{ + {0x0, DTYPE_VISIBLE_STRING, 48, ATYPE_RO, acName1008_0, 0, "k2gice"}, +}; +const _objd SDO1009[] = +{ + {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, 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, 0x1234, NULL}, + {0x03, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_03, 0, NULL}, + {0x04, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_04, 0x00000000, NULL}, +}; +const _objd SDO1600[] = +{ + {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1600_00, 1, NULL}, + {0x01, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_01, 0x70000020, NULL}, +}; +const _objd SDO1A00[] = +{ + {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1A00_00, 1, NULL}, + {0x01, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_01, 0x60000020, NULL}, +}; +const _objd SDO1C00[] = +{ + {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_00, 4, NULL}, + {0x01, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_01, 1, NULL}, + {0x02, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_02, 2, NULL}, + {0x03, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_03, 3, NULL}, + {0x04, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_04, 4, NULL}, +}; +const _objd SDO1C12[] = +{ + {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C12_00, 1, NULL}, + {0x01, DTYPE_UNSIGNED16, 16, ATYPE_RO, acName1C12_01, 0x1600, NULL}, +}; +const _objd SDO1C13[] = +{ + {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C13_00, 1, NULL}, + {0x01, DTYPE_UNSIGNED16, 16, ATYPE_RO, acName1C13_01, 0x1A00, NULL}, +}; +const _objd SDO6000[] = +{ + {0x0, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName6000_0, 0, &Rb.BUTTON}, +}; +const _objd SDO7000[] = +{ + {0x0, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName7000_0, 0, &Wb.LED}, +}; + +const _objectlist SDOobjects[] = +{ + {0x1000, OTYPE_VAR, 0, 0, acName1000, SDO1000}, + {0x1008, OTYPE_VAR, 0, 0, acName1008, SDO1008}, + {0x1009, OTYPE_VAR, 0, 0, acName1009, SDO1009}, + {0x100A, OTYPE_VAR, 0, 0, acName100A, SDO100A}, + {0x1018, OTYPE_RECORD, 4, 0, acName1018, SDO1018}, + {0x1600, OTYPE_RECORD, 1, 0, acName1600, SDO1600}, + {0x1A00, OTYPE_RECORD, 1, 0, acName1A00, SDO1A00}, + {0x1C00, OTYPE_ARRAY, 4, 0, acName1C00, SDO1C00}, + {0x1C12, OTYPE_ARRAY, 1, 0, acName1C12, SDO1C12}, + {0x1C13, OTYPE_ARRAY, 1, 0, acName1C13, SDO1C13}, + {0x6000, OTYPE_VAR, 0, 0, acName6000, SDO6000}, + {0x7000, OTYPE_VAR, 0, 0, acName7000, SDO7000}, + {0xffff, 0xff, 0xff, 0xff, NULL, NULL} +}; +#endif diff --git a/applications/tiesc_k2gice/main.c b/applications/tiesc_k2gice/main.c new file mode 100644 index 0000000..e808b81 --- /dev/null +++ b/applications/tiesc_k2gice/main.c @@ -0,0 +1,86 @@ +#include "k2gice.h" +#include "esc_hw.h" +#include "config.h" +#include +#include "tiescutils.h" +#include +#include + +/** + * This function reads physical input values and assigns the corresponding members + * of Rb.Buttons + */ +void cb_get_BUTTON() +{ + volatile uint8_t io_input; + Board_readRotarySwitch(&io_input); + Rb.BUTTON = io_input; +} + +/** + * This function writes physical output values from the corresponding members of + * Wb.LEDs + */ +void cb_set_LED() +{ + volatile uint8_t io_output; + io_output = Wb.LED; + Board_setDigOutput(io_output); +} + + +/* Called from stack when stopping outputs */ +void user_safeoutput (void) +{ + memset(&Wb, 0, (sizeof(Wb))); + Board_setDigOutput(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 = 9999, + .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 = 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 +}; + +int MainInit(void) +{ + ecat_slv_init(&config); + return 0; +} + +void MainLoop(void) +{ + ecat_slv_poll(); + DIG_process(DIG_PROCESS_WD_FLAG); +} + +int main() +{ + common_main(); + return 0; +} diff --git a/applications/tiesc_k2gice/utypes.h b/applications/tiesc_k2gice/utypes.h new file mode 100644 index 0000000..68f5d9a --- /dev/null +++ b/applications/tiesc_k2gice/utypes.h @@ -0,0 +1,41 @@ +#ifndef __UTYPES_H__ +#define __UTYPES_H__ + +#include + +/* Inputs */ +CC_PACKED_BEGIN +typedef struct +{ + uint32_t BUTTON; +} CC_PACKED _Rbuffer; +CC_PACKED_END + +/* Outputs */ +CC_PACKED_BEGIN +typedef struct +{ + uint32_t LED; +} CC_PACKED _Wbuffer; +CC_PACKED_END + +/* Parameters */ +CC_PACKED_BEGIN +typedef struct +{ +} CC_PACKED _Cbuffer; +CC_PACKED_END + +/* Manufacturer specific data */ +CC_PACKED_BEGIN +typedef struct +{ +} CC_PACKED _Mbuffer; +CC_PACKED_END + +extern _Rbuffer Rb; +extern _Wbuffer Wb; +extern _Cbuffer Cb; +extern _Mbuffer Mb; + +#endif /* __UTYPES_H__ */ diff --git a/soes/esc.c b/soes/esc.c index b4d5934..d882a86 100644 --- a/soes/esc.c +++ b/soes/esc.c @@ -543,7 +543,7 @@ uint8_t ESC_mbxprocess (void) } /* outmbx read by master */ - if (ESCvar.mbxoutpost && ESCvar.SM[1].IntR) + if (ESCvar.mbxoutpost && (ESCvar.ALevent & ESCREG_ALEVENT_SM1)) { ESC_ackmbxread (); /* dispose old backup */ diff --git a/soes/hal/tiesc/applInterface.h b/soes/hal/tiesc/applInterface.h new file mode 100644 index 0000000..c8ade2c --- /dev/null +++ b/soes/hal/tiesc/applInterface.h @@ -0,0 +1,6 @@ +#ifndef _APPLINTERFACE_H_ +#define _APPLINTERFACE_H_ + +/* Not used, to be removed */ + +#endif /*_APPLINTERFACE_H_ */ diff --git a/soes/hal/tiesc/ecat_def.h b/soes/hal/tiesc/ecat_def.h new file mode 100644 index 0000000..8605c7a --- /dev/null +++ b/soes/hal/tiesc/ecat_def.h @@ -0,0 +1,29 @@ +#ifndef __ECAT_DEF_H__ +#define __ECAT_DEF_H__ + +#define ESC_DC_SYNC0_CYCLETIME_OFFSET 0x09A0 +#define ESC_SYSTEMTIME_OFFSET 0x0910 +#define ESC_DC_SYNC_ACTIVATION_OFFSET 0x0981 + +#define STATE_INIT ((uint8_t)0x01) + +#ifndef SOES +#define SOES 1 +#endif + +#ifndef VARVOLATILE +#define VARVOLATILE volatile +#endif + +#ifndef AL_EVENT_ENABLED +#define AL_EVENT_ENABLED 1 +#endif + + +int MainInit(void); +void MainLoop(void); + +extern const unsigned char * tiesc_eeprom; +extern int bRunApplication; + +#endif /* __ECAT_DEF_H__ */ diff --git a/soes/hal/tiesc/ecatslv.h b/soes/hal/tiesc/ecatslv.h new file mode 100644 index 0000000..eb328ab --- /dev/null +++ b/soes/hal/tiesc/ecatslv.h @@ -0,0 +1,6 @@ +#ifndef _ECATSLV_H_ +#define _ECATSLV_H_ + +/* Not used, to be removed */ + +#endif /*_ECATSLV_H_ */ diff --git a/soes/hal/tiesc/esc_hw.c b/soes/hal/tiesc/esc_hw.c new file mode 100644 index 0000000..f61341f --- /dev/null +++ b/soes/hal/tiesc/esc_hw.c @@ -0,0 +1,327 @@ +/* + * Licensed under the GNU General Public License version 2 with exceptions. See + * LICENSE file in the project root for full license information + */ + + /** \file + * \brief + * ESC hardware layer functions. + * + * Function to read and write commands to the ESC. Used to read/write ESC + * registers and memory. + */ +#include +#include "cc.h" +#include "esc_hw.h" +#include "esc_eep.h" +#include "k2gice.h" +#include "tiescbsp.h" +#include "tieschw.h" +#include "config.h" + +extern PRUICSS_Handle pruIcss1Handle; +extern uint32_t pd_read_addr_err, pd_write_addr_err; +extern uint32_t pdi_read_fail_cnt, pdi_write_fail_cnt; + +static PRUICSS_Handle escHwPruIcssHandle; + +int bRunApplication; + +static void Esc_readmbx(uint8_t *pData, uint16_t Address, uint16_t Len) +{ + bsp_pdi_mbx_read_start(escHwPruIcssHandle); + bsp_read(escHwPruIcssHandle, pData, Address, Len); + + if(Len >= MBX0_sml - 2) + { + bsp_pdi_mbx_read_complete(escHwPruIcssHandle); + } +} + +static void ESC_readRXPDO(uint8_t *pData, uint16_t Address, uint16_t Len) +{ + int16_t sm_index; + uint16_t ActAddress = bsp_get_process_data_address(escHwPruIcssHandle, Address, Len, + &sm_index); + + if(ActAddress < ESC_ADDR_MEMORY) + { + pd_read_addr_err++; + return; + } + + bsp_read(escHwPruIcssHandle, pData, ActAddress, Len); + bsp_process_data_access_complete(escHwPruIcssHandle, Address, Len, sm_index); +} + +static void ESC_writembox(uint8_t *pData, uint16_t Address, uint16_t Len) +{ + + //Do not write to mailbox if already full + if((bsp_read_byte(escHwPruIcssHandle, + ESC_ADDR_SM1_STATUS) & SM_STATUS_MBX_FULL)) + { + return; + } + + bsp_pdi_mbx_write_start(escHwPruIcssHandle); + bsp_write(escHwPruIcssHandle, pData, Address, Len); + + if(Len >= MBX1_sml - 2) + { + bsp_pdi_mbx_write_complete(escHwPruIcssHandle); + } +} + +static void ESC_writeTXPDO(uint8_t *pData, uint16_t Address, uint16_t Len) +{ + int16_t sm_index; + uint16_t ActualAddr = bsp_get_process_data_address(escHwPruIcssHandle, Address, Len, + &sm_index); + + if(ActualAddr < ESC_ADDR_MEMORY) + { + pd_write_addr_err++; + return; + } + + bsp_write(escHwPruIcssHandle, pData, ActualAddr, Len); + bsp_process_data_access_complete(escHwPruIcssHandle, Address, Len, sm_index); +} + + +/** ESC read function used by the Slave stack. + * + * @param[in] address = address of ESC register to read + * @param[out] buf = pointer to buffer to read in + * @param[in] len = number of bytes to read + */ +void ESC_read (uint16_t address, void *buf, uint16_t len) +{ + uint16_t alevent; + + switch(address) + { + case MBX0_sma: + /* TODO *//*case MBX0_sma_b:*/ + { + Esc_readmbx(buf, address, len); + break; + } + case SM2_sma: + { + ESC_readRXPDO(buf, address, len); + break; + } + case ESCREG_SM0: + case ESCREG_SM1: + case ESCREG_SM2: + case ESCREG_SM3: + { + bsp_read(escHwPruIcssHandle, buf, address, len); + /* Handle special case when SOES batch read SM settings, + * indicate that SM ACTIVATE is read + */ + if(len > 5) + { + uint8_t n = (address - ESC_ADDR_SYNCMAN) >> 3; + bsp_pdi_post_read_indication(escHwPruIcssHandle, ESCREG_SM0ACTIVATE + (n << 3)); + } + break; + } + default: + { + switch(len) + { + case 1: + { + uint8_t *p = buf; + *p = bsp_read_byte(escHwPruIcssHandle, address); + break; + } + case 2: + { + uint16_t *p = buf; + *p = bsp_read_word(escHwPruIcssHandle, address); + break; + } + case 4: + { + uint32_t *p = buf; + *p = bsp_read_dword(escHwPruIcssHandle, address); + break; + } + default: + { + bsp_read(escHwPruIcssHandle, buf, address, len); + bsp_pdi_post_read_indication(escHwPruIcssHandle, address); + break; + } + } + break; + } + } + + alevent = bsp_read_word_isr(escHwPruIcssHandle, ESCREG_ALEVENT); + CC_ATOMIC_SET(ESCvar.ALevent, (etohs(alevent))); +} + +/** ESC write function used by the Slave stack. + * + * @param[in] address = address of ESC register to write + * @param[out] buf = pointer to buffer to write from + * @param[in] len = number of bytes to write + */ +void ESC_write (uint16_t address, void *buf, uint16_t len) +{ + uint16_t alevent; + + switch(address) + { + case MBX1_sma: + /* TODO *//*case MBX1_sma_b:*/ + { + if(len != 1) + { + ESC_writembox(buf, address, len); + } + else + { + bsp_pdi_mbx_write_start(escHwPruIcssHandle); + } + break; + } + case (MBX1_sma + MBX1_sml - 1): + { + /* Handle SM end byte is written */ + uint8_t * p = buf; + bsp_write_byte(escHwPruIcssHandle, *p, address); + bsp_pdi_mbx_write_complete(escHwPruIcssHandle); + break; + } + case SM3_sma: + { + ESC_writeTXPDO(buf, address, len); + break; + } + default: + { + switch(len) + { + case 1: + { + uint8_t * p = buf; + bsp_write_byte(escHwPruIcssHandle, *p, address); + bsp_pdi_write_indication(escHwPruIcssHandle, address, *p); + break; + } + case 2: + { + uint16_t * p = buf; + bsp_write_word(escHwPruIcssHandle, *p, address); + bsp_pdi_write_indication(escHwPruIcssHandle, address, *p); + break; + } + case 4: + { + uint32_t * p = buf; + bsp_write_dword(escHwPruIcssHandle, *p, address); + bsp_pdi_write_indication(escHwPruIcssHandle, address, *p); + break; + } + default: + { + bsp_write(escHwPruIcssHandle, buf, address, len); + bsp_pdi_write_indication(escHwPruIcssHandle, address, 0); + break; + } + } + break; + } + + } + alevent = bsp_read_word_isr(escHwPruIcssHandle, ESCREG_ALEVENT); + CC_ATOMIC_SET(ESCvar.ALevent, (etohs(alevent))); +} + +/** ESC interrupt enable function by the Slave stack in IRQ mode. + * + * @param[in] mask = of interrupts to enable + */ +void ESC_interrupt_enable (uint32_t mask) +{ + uint32_t readmask; + readmask = bsp_read_dword_isr(escHwPruIcssHandle,ESCREG_ALEVENTMASK); + bsp_write_dword(escHwPruIcssHandle, (mask | readmask), ESCREG_ALEVENTMASK); +} + +/** ESC interrupt disable function by the Slave stack in IRQ mode. + * + * @param[in] mask = interrupts to disable + */ +void ESC_interrupt_disable (uint32_t mask) +{ + uint32_t readmask; + readmask = bsp_read_dword_isr(escHwPruIcssHandle,ESCREG_ALEVENTMASK); + bsp_write_dword(escHwPruIcssHandle, (~mask & readmask), ESCREG_ALEVENTMASK); +} + +/** ESC emulated EEPROM handler + */ +void ESC_eep_handler(void) +{ + EEP_process (); + EEP_hw_process(); +} + +/** SYNC0 ISR handler + * + * @param[in] arg = NOT USED + */ +void Sync0_Isr (void) +{ +} + +/** SYNC1 ISR handler + * + * @param[in] arg = NOT USED + */ +void Sync1_Isr (void) +{ +} + +/** PDI ISR handler + * + * @param[in] arg = NOT USED + */ +void PDI_Isr(void) +{ + uint16_t alevent; + + alevent = bsp_read_word_isr(escHwPruIcssHandle,ESCREG_ALEVENT); + CC_ATOMIC_SET(ESCvar.ALevent, etohs(alevent)); + + if(ESCvar.ALevent & ESCREG_ALEVENT_SM2) + { + DIG_process(DIG_PROCESS_OUTPUTS_FLAG | DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG); + } +} + + +/** ESC and CPU related HW init + * + * @param[in] arg = esc_cfg provided by the application + */ +void ESC_init (const esc_cfg_t * config) +{ + escHwPruIcssHandle = pruIcss1Handle; + bsp_set_sm_properties(escHwPruIcssHandle, 0, MBX0_sma, MBX0_sml); + bsp_set_sm_properties(escHwPruIcssHandle, 1, MBX1_sma, MBX1_sml); + bsp_set_sm_properties(escHwPruIcssHandle, 2, SM2_sma, ESCvar.RXPDOsize); + bsp_set_sm_properties(escHwPruIcssHandle, 3, SM3_sma, ESCvar.TXPDOsize); + + bsp_write_dword(escHwPruIcssHandle, 0 , ESCREG_ALEVENTMASK); +} + + + diff --git a/soes/hal/tiesc/esc_hw.h b/soes/hal/tiesc/esc_hw.h new file mode 100644 index 0000000..2a20f4f --- /dev/null +++ b/soes/hal/tiesc/esc_hw.h @@ -0,0 +1,22 @@ +/* + * Licensed under the GNU General Public License version 2 with exceptions. See + * LICENSE file in the project root for full license information + */ + + /** \file + * \brief + * ESC hardware specifoc EEPROM emulation functions. + */ + +#ifndef __esc_hw__ +#define __esc_hw__ + +#include + +void EEP_hw_process (void); +void ESC_eep_handler(void); +void ESC_interrupt_enable (uint32_t mask); +void ESC_interrupt_disable (uint32_t mask); + +#endif + diff --git a/soes/hal/tiesc/esc_hw_eep.c b/soes/hal/tiesc/esc_hw_eep.c new file mode 100644 index 0000000..008b984 --- /dev/null +++ b/soes/hal/tiesc/esc_hw_eep.c @@ -0,0 +1,71 @@ +/* + * Licensed under the GNU General Public License version 2 with exceptions. See + * LICENSE file in the project root for full license information + */ + + /** \file + * \brief + * ESC hardware specific EEPROM emulation functions. + */ + +#include +#include +#include "esc.h" +#include "esc_hw_eep.h" +#include "tieschw.h" + +extern const uint8_t _binary_sii_eeprom_bin_start; +const unsigned char * tiesc_eeprom = &_binary_sii_eeprom_bin_start; +extern uint8_t eeprom_cache[TIESC_EEPROM_SIZE]; + +/** Initialize EEPROM emulation (load default data, validate checksums, ...). + * + */ +void EEP_init (void) +{ +} + +/** EEPROM emulation controller side periodic task. + * + */ +void EEP_hw_process (void) +{ + return; +} + +/** EEPROM read function + * + * @param[in] addr = EEPROM byte address + * @param[out] data = pointer to buffer of output data + * @param[in] count = number of bytes to read + * @return 0 on OK, 1 on error + */ +int8_t EEP_read (uint32_t addr, uint8_t *data, uint16_t count) +{ + if (addr >= TIESC_EEPROM_SIZE) { + return 1; + } + + /* read data from ram buffer */ + memcpy(data, eeprom_cache + addr, count); + + return 0; +} + +/** EEPROM write function + * + * @param[in] addr = EEPROM byte address + * @param[out] data = pointer to buffer of input data + * @param[in] count = number of bytes to write + * @return 0 on OK, 1 on error + */ +int8_t EEP_write (uint32_t addr, uint8_t *data, uint16_t count) +{ + + /* write data to ram buffer */ + memcpy(eeprom_cache + addr, data, count); + + return 0; +} + + diff --git a/soes/hal/tiesc/esc_hw_eep.h b/soes/hal/tiesc/esc_hw_eep.h new file mode 100644 index 0000000..fcb80b0 --- /dev/null +++ b/soes/hal/tiesc/esc_hw_eep.h @@ -0,0 +1,23 @@ +/* + * Licensed under the GNU General Public License version 2 with exceptions. See + * LICENSE file in the project root for full license information + */ + + /** \file + * \brief + * ESC hardware specifoc EEPROM emulation functions. + */ + +#ifndef __esc_hw_eep__ +#define __esc_hw_eep__ + +#include +#include "esc_eep.h" + + +/* periodic task */ +void EEP_hw_process (void); + +#endif + +