Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: EasyCAT.h
- Revision:
- 0:7816b38c99cc
- Child:
- 4:66867fae2256
diff -r 000000000000 -r 7816b38c99cc EasyCAT.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EasyCAT.h Tue Sep 12 17:09:43 2017 +0000
@@ -0,0 +1,424 @@
+//********************************************************************************************
+// *
+// AB&T Tecnologie Informatiche - Ivrea Italy *
+// http://www.bausano.net *
+// https://www.ethercat.org/en/products/791FFAA126AD43859920EA64384AD4FD.htm *
+// *
+//********************************************************************************************
+// *
+// This software is distributed as an example, in the hope that it could be useful, *
+// WITHOUT ANY WARRANTY, even the implied warranty of FITNESS FOR A PARTICULAR PURPOSE *
+// *
+//********************************************************************************************
+
+
+//----- EasyCAT library for mbed boards 170912 ----------------------------------------------
+//----- Derived from the AB&T EasyCAT Arduino shield library V 1.5 --------------------------
+
+//----- Tested with the STM32 NUCLEO-F767ZI board -------------------------------------------
+
+
+
+
+#ifndef EasyCAT_H
+#define EasyCAT_H
+
+
+
+
+//****** PDO configuration parameters ********************************************************
+
+// Here we can define how many I/O bytes our EasyCAT can exchange
+
+// We can use STANDARD MODE or CUSTOM MODE
+// !!! Warning: CUSTOM MODE is recommended only for advanced users !!!
+
+// In STANDARD MODE the EasyCAT exchanges a fixed number of bytes
+// in input and in output
+// The number of bytes in input are equal to the number of bytes in output
+// Valid values are 16, 32, 64, 128
+//
+// The configuration EEPROM on board of the EasyCAT must be
+// loaded with the corresponding bin file, provided by AB&T
+//
+// The EasyCAT is shipped configured for 32+32 bytes I.E. with
+// the "EasyCAT_32_32.bin" file loaded into the configuration EEPROM
+
+
+//-- BYTE_NUM ----------- Byte exchanged ------ Config EEPROM file
+
+//#define BYTE_NUM 16 // 16 + 16 EasyCAT_16_16.bin
+#define BYTE_NUM 32 // 32 + 32 EasyCAT_32_32.bin
+//#define BYTE_NUM 64 // 64 + 64 EasyCAT_64_64.bin
+//#define BYTE_NUM 128 // 128 + 128 EasyCAT_128_128.bin
+
+
+
+// In CUSTOM MODE, recommended only for advanced users, the EasyCAT exchanges
+// a configurable number of bytes, between 0 and 128, in input and in output
+// The number of bytes in input and in output can be different
+//
+// The configuration EEPROM on board of the EasyCAT must be
+// loaded with a suitable bin file, provided by the user
+// or with the "EasyCAT_configurable.bin" file provided by AB&T
+
+// Comment all the above BYTE_NUM #define for the STANDARD MODE
+// and define here the custom number of exchanged bytes
+
+ //----- CUSTOM_MODE example -------
+ //
+//#define CUST_BYTE_NUM_OUT 49 // total number of bytes in output
+//#define CUST_BYTE_NUM_IN 17 // total number of bytes in input
+
+// We can also customize names and data types for the PDOs
+// see the example in this file (look for tag "Custom data types example")
+
+//*************************************************************************************
+
+
+
+//-- the preprocessor calculates the parameters necessary to transfer out data ---
+
+ // define TOT_BYTE_NUM_OUT as the total
+ // number of byte you need to
+ // transfer in output (between 0 and 128)
+ // this must match your ESI XML
+
+#ifdef BYTE_NUM
+ #define TOT_BYTE_NUM_OUT BYTE_NUM // bytes in output
+#else
+ #define TOT_BYTE_NUM_OUT CUST_BYTE_NUM_OUT // any number between 0 and 128
+#endif
+
+
+#if ((TOT_BYTE_NUM_OUT & 0x03) != 0x00) // number of bytes in output
+ #define TOT_BYTE_NUM_ROUND_OUT ((TOT_BYTE_NUM_OUT | 0x03) + 1)
+#else // rounded to 4 (long)
+ #define TOT_BYTE_NUM_ROUND_OUT TOT_BYTE_NUM_OUT //
+#endif //
+
+#if TOT_BYTE_NUM_OUT > 64 // if we have more then 64 bytes
+ // we have to split the transfer in two
+
+ #define SEC_BYTE_NUM_OUT (TOT_BYTE_NUM_OUT - 64) // number of bytes of the second transfer
+
+ #if ((SEC_BYTE_NUM_OUT & 0x03) != 0x00) // number of bytes of the second transfer
+ #define SEC_BYTE_NUM_ROUND_OUT ((SEC_BYTE_NUM_OUT | 0x03) + 1)
+ #else // rounded to 4 (long)
+ #define SEC_BYTE_NUM_ROUND_OUT SEC_BYTE_NUM_OUT//
+ #endif //
+
+ #define SEC_LONG_NUM_OUT SEC_BYTE_NUM_ROUND_OUT/4// number of long of the second transfer
+
+ #define FST_BYTE_NUM_OUT 64 // number of bytes of the first transfer
+ #define FST_BYTE_NUM_ROUND_OUT 64 // number of bytes of the first transfer
+ // rounded to 4 (long)
+ #define FST_LONG_NUM_OUT 16 // number of long of the second transfer
+
+
+#else // if we have 64 bytes max we tranfert
+ // them in just one round
+
+ #define FST_BYTE_NUM_OUT TOT_BYTE_NUM_OUT // number of bytes of the first and only transfer
+
+ #if ((FST_BYTE_NUM_OUT & 0x03) != 0x00) // number of bytes of the first and only transfer
+ #define FST_BYTE_NUM_ROUND_OUT ((FST_BYTE_NUM_OUT | 0x03) + 1)
+ #else // rounded to 4 (long)
+ #define FST_BYTE_NUM_ROUND_OUT FST_BYTE_NUM_OUT
+ #endif
+
+ #define FST_LONG_NUM_OUT FST_BYTE_NUM_ROUND_OUT/4// number of long of the first and only transfer
+
+ #define SEC_BYTE_NUM_OUT 0 // we don't use the second round
+ #define SEC_BYTE_NUM_ROUND_OUT 0 //
+ #define SEC_LONG_NUM_OUT 0 //
+
+#endif
+
+
+//-- the preprocessor calculates the parameters necessary to transfer in data ---
+
+ // define TOT_BYTE_NUM_IN the total
+ // number of byte you need to
+ // transfer in input (between 0 and 128)
+
+#ifdef BYTE_NUM
+ #define TOT_BYTE_NUM_IN BYTE_NUM // bytes in input
+#else
+ #define TOT_BYTE_NUM_IN CUST_BYTE_NUM_IN // any number between 0 and 128
+#endif
+
+
+#if ((TOT_BYTE_NUM_IN & 0x03) != 0x00) // number of bytes in output
+ #define TOT_BYTE_NUM_ROUND_IN ((TOT_BYTE_NUM_IN | 0x03) + 1)
+#else // rounded to 4 (long)
+ #define TOT_BYTE_NUM_ROUND_IN TOT_BYTE_NUM_IN //
+#endif //
+
+#if TOT_BYTE_NUM_IN > 64 // if we have more then 64 bytes
+ // we have to split the transfer in two
+
+ #define SEC_BYTE_NUM_IN (TOT_BYTE_NUM_IN - 64) // number of bytes of the second transfer
+
+ #if ((SEC_BYTE_NUM_IN & 0x03) != 0x00) // number of bytes of the second transfer
+ #define SEC_BYTE_NUM_ROUND_IN ((SEC_BYTE_NUM_IN | 0x03) + 1)
+ #else // rounded to 4 (long)
+ #define SEC_BYTE_NUM_ROUND_IN SEC_BYTE_NUM_IN //
+ #endif //
+
+ #define SEC_LONG_NUM_IN SEC_BYTE_NUM_ROUND_IN/4 // number of long of the second transfer
+
+ #define FST_BYTE_NUM_IN 64 // number of bytes of the first transfer
+ #define FST_BYTE_NUM_ROUND_IN 64 // number of bytes of the first transfer
+ // rounded to 4 (long)
+ #define FST_LONG_NUM_IN 16 // number of long of the second transfer
+
+
+#else // if we have 64 bytes max we tranfert
+ // them in just one round
+
+ #define FST_BYTE_NUM_IN TOT_BYTE_NUM_IN // number of bytes of the first and only transfer
+
+ #if ((FST_BYTE_NUM_IN & 0x03) != 0x00) // number of bytes of the first and only transfer
+ #define FST_BYTE_NUM_ROUND_IN ((FST_BYTE_NUM_IN | 0x03) + 1)
+ #else // rounded to 4 (long)
+ #define FST_BYTE_NUM_ROUND_IN FST_BYTE_NUM_IN
+ #endif
+
+ #define FST_LONG_NUM_IN FST_BYTE_NUM_ROUND_IN/4 // number of long of the first and only transfer
+
+ #define SEC_BYTE_NUM_IN 0 // we don't use the second round
+ #define SEC_BYTE_NUM_ROUND_IN 0 //
+ #define SEC_LONG_NUM_IN 0 //
+
+#endif
+
+
+//---------------------------------------------------------------------------------
+
+//----------------- sanity check -------------------------------------------------------
+
+
+#ifdef BYTE_NUM // STANDARD MODE and CUSTOM MODE
+ // cannot be defined at the same time
+ #ifdef CUST_BYTE_NUM_OUT
+ #error "BYTE_NUM and CUST_BYTE_NUM_OUT cannot be defined at the same time !!!!"
+ #error "define them correctly in file EasyCAT.h"
+ #endif
+
+ #ifdef CUST_BYTE_NUM_IN
+ #error "BYTE_NUM and CUST_BYTE_NUM_IN cannot be defined at the same time !!!!"
+ #error "define them correctly in file EasyCAT.h"
+ #endif
+#endif
+
+#ifdef BYTE_NUM //--- for BYTE_NUM we accept only 16 32 64 128 --
+
+ #if ((BYTE_NUM !=16) && (BYTE_NUM !=32) && (BYTE_NUM !=64) && (BYTE_NUM !=128))
+ #error "BYTE_NUM must be 16, 32, 64 or 128 !!! define it correctly in file EasyCAT.h"
+ #endif
+
+#else
+ //--- CUST_BYTE_NUM_OUT and CUST_BYTE_NUM_IN --------
+ // must be max 128
+ #if (CUST_BYTE_NUM_OUT > 128)
+ #error "CUST_BYTE_NUM_OUT must be max 128 !!! define it correctly in file EasyCAT.h"
+ #endif
+
+ #if (CUST_BYTE_NUM_IN > 128)
+ #error "CUST_BYTE_NUM_IN must be max 128 !!! define it correctly in file EasyCAT.h"
+ #endif
+
+#endif
+
+
+//*************************************************************************************************
+
+
+
+
+//---- LAN9252 registers --------------------------------------------------------------------------
+
+ //---- access to EtherCAT registers -------------------
+
+#define ECAT_CSR_DATA 0x0300 // EtherCAT CSR Interface Data Register
+#define ECAT_CSR_CMD 0x0304 // EtherCAT CSR Interface Command Register
+
+
+ //---- access to EtherCAT process RAM -----------------
+
+#define ECAT_PRAM_RD_ADDR_LEN 0x0308 // EtherCAT Process RAM Read Address and Length Register
+#define ECAT_PRAM_RD_CMD 0x030C // EtherCAT Process RAM Read Command Register
+#define ECAT_PRAM_WR_ADDR_LEN 0x0310 // EtherCAT Process RAM Write Address and Length Register
+#define ECAT_PRAM_WR_CMD 0x0314 // EtherCAT Process RAM Write Command Register
+
+#define ECAT_PRAM_RD_DATA 0x0000 // EtherCAT Process RAM Read Data FIFO
+#define ECAT_PRAM_WR_DATA 0x0020 // EtherCAT Process RAM Write Data FIFO
+
+ //---- EtherCAT registers -----------------------------
+
+#define AL_STATUS 0x0130 // AL status
+#define WDOG_STATUS 0x0440 // watch dog status
+#define AL_EVENT_MASK 0x0204 // AL event interrupt mask
+
+ //---- LAN9252 registers ------------------------------
+
+#define HW_CFG 0x0074 // hardware configuration register
+#define BYTE_TEST 0x0064 // byte order test register
+#define RESET_CTL 0x01F8 // reset register
+#define ID_REV 0x0050 // chip ID and revision
+#define IRQ_CFG 0x0054 // interrupt configuration
+#define INT_EN 0x005C // interrupt enable
+
+
+//---- LAN9252 flags ------------------------------------------------------------------------------
+
+#define ECAT_CSR_BUSY 0x80
+
+#define PRAM_ABORT 0x40000000
+
+#define PRAM_BUSY 0x80
+
+#define PRAM_AVAIL 0x01
+
+#define READY 0x08
+
+#define DIGITAL_RST 0x00000001
+
+
+//---- EtherCAT flags -----------------------------------------------------------------------------
+
+ // EtherCAT state machine
+
+#define ESM_INIT 0x01 // init
+#define ESM_PREOP 0x02 // pre-operational
+#define ESM_BOOT 0x03 // bootstrap
+#define ESM_SAFEOP 0x04 // safe-operational
+#define ESM_OP 0x08 // operational
+
+
+//--- ESC commands --------------------------------------------------------------------------------
+
+#define ESC_WRITE 0x80
+#define ESC_READ 0xC0
+
+
+//---- SPI ----------------------------------------------------------------------------------------
+
+#define COMM_SPI_READ 0x03
+#define COMM_SPI_WRITE 0x02
+
+#define DUMMY_BYTE 0xFF
+
+
+
+//---- typedef ------------------------------------------------------------------------------------
+
+typedef union
+{
+ unsigned short Word;
+ unsigned char Byte[2];
+} UWORD;
+
+typedef union
+{
+ unsigned long Long;
+ unsigned short Word[2];
+ unsigned char Byte[4];
+} ULONG;
+
+
+typedef union //-- output buffer -----------------
+{ //
+ uint8_t Byte [TOT_BYTE_NUM_ROUND_OUT]; //
+
+ #if CUST_BYTE_NUM_OUT > 0 //----- Custom data types example -----
+/* //
+ struct // Here we can define our custom
+ { // data types and names for the outputs
+ //
+ uint8_t Control; // The total number of bytes declared
+ float PreZone1; // in this structure must be equal
+ float CommZone1; // to the value assigned to CUST_BYTE_NUM_OUT
+ float RampZone1; //
+ float PreZone2; // In this case 1+ 4+4+4+ 4+4+4+ 4+4+4+ 4+4+4 = 49
+ float CommZone2; //
+ float RampZone2; //
+ float PreZone3; //
+ float CommZone3; //
+ float RampZone3; //
+ float PreZone4; //
+ float CommZone4; //
+ float RampZone4; //
+ }Cust; //
+*/ //
+ #endif //
+
+} PROCBUFFER_OUT; //
+
+
+typedef union //-- input buffer ------------------
+{ //
+ uint8_t Byte [TOT_BYTE_NUM_ROUND_IN]; //
+
+ #if CUST_BYTE_NUM_IN > 0 //----- Custom data types example ------
+/* //
+ struct // Here we can define our custom
+ { // data types and names for the inputs
+ //
+ uint8_t Status; // The total number of bytes declared
+ float TempZone1; // in this structure must be equal
+ float TempZone2; // to the value assigned to CUST_BYTE_NUM_IN
+ float TempZone3; //
+ float TempZone4; // In this case 1+ 4+4+4+4 = 17
+ }Cust; //
+*/ //
+ #endif //
+
+} PROCBUFFER_IN; //
+
+
+typedef enum
+{
+ ASYNC,
+ DC_SYNC,
+ SM_SYNC
+}SyncMode;
+
+
+
+//-------------------------------------------------------------------------------------------------
+
+class EasyCAT
+{
+ public:
+ EasyCAT(); // default constructor
+ EasyCAT(PinName SCS);
+ EasyCAT(SyncMode Sync);
+ EasyCAT(PinName SCS, SyncMode Sync);
+
+
+ unsigned char MainTask(); // EtherCAT main task
+ // must be called cyclically by the application
+
+ bool Init(); // EasyCAT board initialization
+
+ PROCBUFFER_OUT BufferOut; // output process data buffer
+ PROCBUFFER_IN BufferIn; // input process data buffer
+
+
+ private:
+ void SPIWriteRegisterDirect (unsigned short Address, unsigned long DataOut);
+ unsigned long SPIReadRegisterDirect (unsigned short Address, unsigned char Len);
+
+ void SPIWriteRegisterIndirect (unsigned long DataOut, unsigned short Address, unsigned char Len);
+ unsigned long SPIReadRegisterIndirect (unsigned short Address, unsigned char Len);
+
+ void SPIReadProcRamFifo();
+ void SPIWriteProcRamFifo();
+
+ PinName SCS_;
+ SyncMode Sync_;
+};
+
+#endif