Merge pull request #15 from nakarlsson/master

Add support and sample project for LAN9252
pull/18/head
Mikael Heden 2017-01-13 09:27:48 +01:00 committed by GitHub
commit 56bd0169b7
11 changed files with 1993 additions and 0 deletions

View File

@ -0,0 +1,35 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
#include <cc.h>
#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__ */

View File

@ -0,0 +1,49 @@
#include <kern.h>
#include "slave.h"
/**
* This function reads physical input values and assigns the corresponding members
* of Rb.Buttons
*/
void cb_get_Buttons()
{
}
/**
* This function writes physical output values from the corresponding members of
* Wb.LEDs
*/
void cb_set_LEDs()
{
}
/**
* This function is called after a SDO write of the object Cb.Parameters.
*/
void cb_post_write_Parameters(int subindex)
{
}
void main_run(void * arg)
{
soes_init();
while(1) {
soes();
}
}
int main(void)
{
rprintf("Hello Main\n");
task_spawn ("soes", main_run, 8, 2048, NULL);
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,265 @@
#include <stddef.h>
#include "utypes.h"
#include "soes/esc.h"
#include "soes/esc_coe.h"
#include "soes/esc_foe.h"
#include "slave.h"
#ifndef EEP_EMULATION
#define EEP_EMULATION 0 /* Set to 1 for EEPROM emulation */
#endif
#define WATCHDOG_RESET_VALUE 150
#define DEFAULTTXPDOMAP 0x1a00
#define DEFAULTRXPDOMAP 0x1600
#define DEFAULTTXPDOITEMS 1
#define DEFAULTRXPDOITEMS 1
volatile _ESCvar ESCvar;
_MBX MBX[MBXBUFFERS];
_MBXcontrol MBXcontrol[MBXBUFFERS];
uint8_t MBXrun=0;
uint16_t SM2_sml,SM3_sml;
_Rbuffer Rb;
_Wbuffer Wb;
_Cbuffer Cb;
_App App;
uint16_t TXPDOsize,RXPDOsize;
uint16_t txpdomap = DEFAULTTXPDOMAP;
uint16_t rxpdomap = DEFAULTRXPDOMAP;
uint8_t txpdoitems = DEFAULTTXPDOITEMS;
uint8_t rxpdoitems = DEFAULTTXPDOITEMS;
static unsigned int watchdog = WATCHDOG_RESET_VALUE;
static void (*application_loop_callback)(void) = NULL;
/** 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)
{
case 0x1c12:
{
if (rxpdoitems > 1)
{
rxpdoitems = 1;
}
if ((rxpdomap != 0x1600) && (rxpdomap != 0x1601)
&& (rxpdomap != 0x0000))
{
rxpdomap = 0x1600;
}
RXPDOsize = SM2_sml = sizeRXPDO();
break;
}
case 0x1c13:
{
if (txpdoitems > 1)
{
txpdoitems = 1;
}
if ((txpdomap != 0x1A00) && (txpdomap != 0x1A01)
&& (rxpdomap != 0x0000))
{
txpdomap = 0x1A00;
}
TXPDOsize = SM3_sml = sizeTXPDO();
break;
}
/* Handle post-write of parameter values */
case 0x8000:
{
cb_post_write_Parameters(subindex);
break;
}
default:
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");
// Set safe values for Wb.LEDs
Wb.LEDs.LED0 = 0;
Wb.LEDs.LED1 = 0;
}
/** Mandatory: Write local process data to Sync Manager 3, Master Inputs.
*/
void TXPDO_update (void)
{
ESC_write (SM3_sma, &Rb, TXPDOsize);
}
/** Mandatory: Read Sync Manager 2 to local process data, Master Outputs.
*/
void RXPDO_update (void)
{
ESC_read (SM2_sma, &Wb, 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 (void)
{
if (watchdog > 0)
{
watchdog--;
}
if (App.state & APPSTATE_OUTPUT)
{
/* SM2 trigger ? */
if (ESCvar.ALevent & ESCREG_ALEVENT_SM2)
{
ESCvar.ALevent &= ~ESCREG_ALEVENT_SM2;
RXPDO_update();
watchdog = WATCHDOG_RESET_VALUE;
/* Set outputs */
cb_set_LEDs();
}
if (watchdog == 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
{
watchdog = WATCHDOG_RESET_VALUE;
}
if (App.state)
{
/* Update inputs */
cb_get_Buttons();
TXPDO_update();
}
}
/********** TODO: Generic code beyond this point ***************/
static const char *spi_name = "/spi1/lan9252";
/** 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 0
/* Add specific step change hooks here */
if ((*as == BOOT_TO_INIT) && (*an == ESCinit))
{
boot_inithook();
}
else if((*as == INIT_TO_BOOT) && (*an & ESCerror ) == 0)
{
init_boothook();
}
#endif
}
/**
* Set callback run once every loop in the SOES application loop.
*/
void set_application_loop_hook(void (*callback)(void))
{
application_loop_callback = callback;
}
/**
* SOES main function. It should be called periodically.
* Reads the EtherCAT state and status. Responsible for I/O updates.
*/
void soes (void)
{
/* On init restore PDO mappings to default size */
if((ESCvar.ALstatus & 0x0f) == ESCinit)
{
txpdomap = DEFAULTTXPDOMAP;
rxpdomap = DEFAULTRXPDOMAP;
txpdoitems = DEFAULTTXPDOITEMS;
rxpdoitems = DEFAULTTXPDOITEMS;
}
/* 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 mailboxes */
if (ESC_mbxprocess())
{
ESC_coeprocess();
ESC_foeprocess();
ESC_xoeprocess();
}
DIG_process();
#if EEP_EMULATION
EEP_process ();
EEP_hw_process();
#endif /* EEP_EMULATION */
if (application_loop_callback != NULL)
{
(application_loop_callback)();
}
}
/**
* Initialize the SOES stack.
*/
void soes_init (void)
{
DPRINT ("SOES (Simple Open EtherCAT Slave)\n");
TXPDOsize = SM3_sml = sizeTXPDO();
RXPDOsize = SM2_sml = sizeRXPDO();
/* Setup post config hooks */
static esc_cfg_t config =
{
.pre_state_change_hook = NULL,
.post_state_change_hook = post_state_change_hook
};
ESC_config ((esc_cfg_t *)&config);
ESC_reset();
ESC_init ((void *)spi_name);
/* 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();
}

View File

@ -0,0 +1,298 @@
<?xml version="1.0" encoding="UTF-8"?>
<Slave id="evb9252_dig" productCode="1234">
<Name>lan9252</Name>
<Vendor>
<Id>0x1337</Id>
<Name>rt-labs AB</Name>
</Vendor>
<Group>
<Type>lan9252_spi</Type>
<Name>lan9252</Name>
</Group>
<Fmmu>Outputs</Fmmu>
<Fmmu>Inputs</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="0x20" DefaultSize="0" StartAddress="0x1180">Inputs</Sm>
<Mailbox CoE="true" FoE="true">
<Bootstrap Length="128" Start="0x1000"/>
<Standard Length="128" Start="0x1000"/>
</Mailbox>
<Eeprom>
<ConfigData>8002000000000000</ConfigData>
<BootStrap>0010800080108000</BootStrap>
</Eeprom>
<Dictionary>
<Item>
<Name>Device Type</Name>
<Index>0x1000</Index>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x01901389</DefaultValue>
</Item>
<Item Managed="true">
<Name>Device Name</Name>
<Index>0x1008</Index>
<DataType>VISIBLE_STRING</DataType>
<DefaultValue>evb9252_dig</DefaultValue>
</Item>
<Item>
<Name>Hardware Version</Name>
<Index>0x1009</Index>
<DataType>VISIBLE_STRING</DataType>
<DefaultValue>1.0</DefaultValue>
</Item>
<Item>
<Name>Software Version</Name>
<Index>0x100A</Index>
<DataType>VISIBLE_STRING</DataType>
<DefaultValue>1.0</DefaultValue>
</Item>
<Item Managed="true">
<Name>Identity Object</Name>
<Index>0x1018</Index>
<DataType>RECORD</DataType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>4</DefaultValue>
</SubItem>
<SubItem>
<Name>Vendor ID</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x1337</DefaultValue>
</SubItem>
<SubItem>
<Name>Product Code</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>1234</DefaultValue>
</SubItem>
<SubItem>
<Name>Revision Number</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0</DefaultValue>
</SubItem>
<SubItem>
<Name>Serial Number</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x00000000</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Name>LEDs</Name>
<Index>0x1600</Index>
<DataType>RECORD</DataType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>2</DefaultValue>
</SubItem>
<SubItem>
<Name>LED0</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000108</DefaultValue>
</SubItem>
<SubItem>
<Name>LED1</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000208</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Name>Buttons</Name>
<Index>0x1A00</Index>
<DataType>RECORD</DataType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Name>Button1</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x60000108</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Name>Sync Manager Communication Type</Name>
<Index>0x1C00</Index>
<DataType>ARRAY</DataType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>4</DefaultValue>
</SubItem>
<SubItem>
<Name>Communications Type SM0</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Name>Communications Type SM1</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>2</DefaultValue>
</SubItem>
<SubItem>
<Name>Communications Type SM2</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>3</DefaultValue>
</SubItem>
<SubItem>
<Name>Communications Type SM3</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>4</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Name>Sync Manager 2 PDO Assignment</Name>
<Index>0x1C12</Index>
<DataType>ARRAY</DataType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Name>PDO Mapping</Name>
<DataType>UNSIGNED16</DataType>
<DefaultValue>0x1600</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Name>Sync Manager 3 PDO Assignment</Name>
<Index>0x1C13</Index>
<DataType>ARRAY</DataType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Name>PDO Mapping</Name>
<DataType>UNSIGNED16</DataType>
<DefaultValue>0x1A00</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Name>Buttons</Name>
<Index>0x6000</Index>
<DataType>RECORD</DataType>
<Variable>Buttons</Variable>
<VariableType>Input</VariableType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Name>Button1</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>0</DefaultValue>
<Access>RO</Access>
<Variable>Button1</Variable>
<VariableType>Input</VariableType>
</SubItem>
</Item>
<Item Managed="true">
<Name>LEDs</Name>
<Index>0x7000</Index>
<DataType>RECORD</DataType>
<Variable>LEDs</Variable>
<VariableType>Output</VariableType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>2</DefaultValue>
</SubItem>
<SubItem>
<Name>LED0</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>0</DefaultValue>
<Access>RO</Access>
<Variable>LED0</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Name>LED1</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>0</DefaultValue>
<Access>RO</Access>
<Variable>LED1</Variable>
<VariableType>Output</VariableType>
</SubItem>
</Item>
<Item Managed="true">
<Name>Parameters</Name>
<Index>0x8000</Index>
<DataType>RECORD</DataType>
<Variable>Parameters</Variable>
<VariableType>Parameter</VariableType>
<SubItem>
<Name>Number of Elements</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Name>Multiplier</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0</DefaultValue>
<Access>RW</Access>
<Variable>Multiplier</Variable>
<VariableType>Parameter</VariableType>
</SubItem>
</Item>
</Dictionary>
<RxPdo>
<Index>0x1600</Index>
<Container>LEDs</Container>
<Name>LEDs</Name>
<Entry>
<Index>0x7000</Index>
<SubIndex>1</SubIndex>
<Variable>LED0</Variable>
</Entry>
<Entry>
<Index>0x7000</Index>
<SubIndex>2</SubIndex>
<Variable>LED1</Variable>
</Entry>
</RxPdo>
<TxPdo>
<Index>0x1A00</Index>
<Container>Buttons</Container>
<Name>Buttons</Name>
<Entry>
<Index>0x6000</Index>
<SubIndex>1</SubIndex>
<Variable>Button1</Variable>
</Entry>
</TxPdo>
<Input>
<Name>Buttons</Name>
<Type>RECORD</Type>
<Member>
<Name>Button1</Name>
<Type>UNSIGNED8</Type>
</Member>
</Input>
<Output>
<Name>LEDs</Name>
<Type>RECORD</Type>
<Member>
<Name>LED0</Name>
<Type>UNSIGNED8</Type>
</Member>
<Member>
<Name>LED1</Name>
<Type>UNSIGNED8</Type>
</Member>
</Output>
<Parameter>
<Name>Parameters</Name>
<Type>RECORD</Type>
<Member>
<Name>Multiplier</Name>
<Type>UNSIGNED32</Type>
</Member>
</Parameter>
</Slave>

View File

@ -0,0 +1,38 @@
#ifndef __SLAVE_H__
#define __SLAVE_H__
#include "utypes.h"
/**
* This function reads physical input values and assigns the corresponding members
* of Rb.Buttons
*/
void cb_get_Buttons();
/**
* This function writes physical output values from the corresponding members of
* Wb.LEDs
*/
void cb_set_LEDs();
/**
* This function is called after a SDO write of the object Cb.Parameters.
*/
void cb_post_write_Parameters(int subindex);
/**
* This function sets an application loop callback function.
*/
void set_application_loop_hook(void (*callback)(void));
/**
* Main function for SOES application
*/
void soes (void);
/**
* Initialize the SOES stack
*/
void soes_init (void);
#endif /* __SLAVE_H__ */

View File

@ -0,0 +1,691 @@
<?xml version="1.0" encoding="UTF-8"?>
<EtherCATInfo>
<Vendor>
<Id>#x1337</Id>
<Name LcId="1033">rt-labs AB</Name>
</Vendor>
<Descriptions>
<Groups>
<Group>
<Type>lan9252_spi</Type>
<Name LcId="1033">lan9252</Name>
</Group>
</Groups>
<Devices>
<Device Physics="YY">
<Type ProductCode="1234" RevisionNo="0">evb9252_dig</Type>
<Name LcId="1033">lan9252</Name>
<GroupType>lan9252_spi</GroupType>
<Profile>
<ProfileNo>5001</ProfileNo>
<AddInfo>400</AddInfo>
<Dictionary>
<DataTypes>
<DataType>
<Name>DT1018</Name>
<BitSize>144</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>1</SubIdx>
<Name>Vendor ID</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>2</SubIdx>
<Name>Product Code</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>48</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>3</SubIdx>
<Name>Revision Number</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>80</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>4</SubIdx>
<Name>Serial Number</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>112</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT1600</Name>
<BitSize>80</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>1</SubIdx>
<Name>LED0</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>2</SubIdx>
<Name>LED1</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>48</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT1A00</Name>
<BitSize>48</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>1</SubIdx>
<Name>Button1</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT1C00ARR</Name>
<BaseType>USINT</BaseType>
<BitSize>32</BitSize>
<ArrayInfo>
<LBound>1</LBound>
<Elements>4</Elements>
</ArrayInfo>
</DataType>
<DataType>
<Name>DT1C00</Name>
<BitSize>48</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<Name>Elements</Name>
<Type>DT1C00ARR</Type>
<BitSize>32</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT1C12ARR</Name>
<BaseType>UINT</BaseType>
<BitSize>16</BitSize>
<ArrayInfo>
<LBound>1</LBound>
<Elements>1</Elements>
</ArrayInfo>
</DataType>
<DataType>
<Name>DT1C12</Name>
<BitSize>32</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<Name>Elements</Name>
<Type>DT1C12ARR</Type>
<BitSize>16</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT1C13ARR</Name>
<BaseType>UINT</BaseType>
<BitSize>16</BitSize>
<ArrayInfo>
<LBound>1</LBound>
<Elements>1</Elements>
</ArrayInfo>
</DataType>
<DataType>
<Name>DT1C13</Name>
<BitSize>32</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<Name>Elements</Name>
<Type>DT1C13ARR</Type>
<BitSize>16</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT6000</Name>
<BitSize>24</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>1</SubIdx>
<Name>Button1</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT7000</Name>
<BitSize>32</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>1</SubIdx>
<Name>LED0</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>2</SubIdx>
<Name>LED1</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>24</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>DT8000</Name>
<BitSize>48</BitSize>
<SubItem>
<SubIdx>0</SubIdx>
<Name>Number of Elements</Name>
<Type>USINT</Type>
<BitSize>8</BitSize>
<BitOffs>0</BitOffs>
<Flags>
<Access>ro</Access>
</Flags>
</SubItem>
<SubItem>
<SubIdx>1</SubIdx>
<Name>Multiplier</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<BitOffs>16</BitOffs>
<Flags>
<Access>rw</Access>
</Flags>
</SubItem>
</DataType>
<DataType>
<Name>STRING(3)</Name>
<BitSize>24</BitSize>
</DataType>
<DataType>
<Name>STRING(11)</Name>
<BitSize>88</BitSize>
</DataType>
<DataType>
<Name>UDINT</Name>
<BitSize>32</BitSize>
</DataType>
<DataType>
<Name>UINT</Name>
<BitSize>16</BitSize>
</DataType>
<DataType>
<Name>USINT</Name>
<BitSize>8</BitSize>
</DataType>
</DataTypes>
<Objects>
<Object>
<Index>#x1000</Index>
<Name>Device Type</Name>
<Type>UDINT</Type>
<BitSize>32</BitSize>
<Info>
<DefaultValue>#x01901389</DefaultValue>
</Info>
<Flags>
<Access>ro</Access>
<Category>m</Category>
</Flags>
</Object>
<Object>
<Index>#x1008</Index>
<Name>Device Name</Name>
<Type>STRING(11)</Type>
<BitSize>88</BitSize>
<Info>
<DefaultString>evb9252_dig</DefaultString>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x1009</Index>
<Name>Hardware Version</Name>
<Type>STRING(3)</Type>
<BitSize>24</BitSize>
<Info>
<DefaultString>1.0</DefaultString>
</Info>
<Flags>
<Access>ro</Access>
<Category>o</Category>
</Flags>
</Object>
<Object>
<Index>#x100A</Index>
<Name>Software Version</Name>
<Type>STRING(3)</Type>
<BitSize>24</BitSize>
<Info>
<DefaultString>1.0</DefaultString>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x1018</Index>
<Name>Identity Object</Name>
<Type>DT1018</Type>
<BitSize>144</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>4</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Vendor ID</Name>
<Info>
<DefaultValue>#x1337</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Product Code</Name>
<Info>
<DefaultValue>1234</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Revision Number</Name>
<Info>
<DefaultValue>0</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Serial Number</Name>
<Info>
<DefaultValue>#x00000000</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x1600</Index>
<Name>LEDs</Name>
<Type>DT1600</Type>
<BitSize>80</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>2</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>LED0</Name>
<Info>
<DefaultValue>#x70000108</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>LED1</Name>
<Info>
<DefaultValue>#x70000208</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x1A00</Index>
<Name>Buttons</Name>
<Type>DT1A00</Type>
<BitSize>48</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>1</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Button1</Name>
<Info>
<DefaultValue>#x60000108</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x1C00</Index>
<Name>Sync Manager Communication Type</Name>
<Type>DT1C00</Type>
<BitSize>48</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>4</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Communications Type SM0</Name>
<Info>
<DefaultValue>1</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Communications Type SM1</Name>
<Info>
<DefaultValue>2</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Communications Type SM2</Name>
<Info>
<DefaultValue>3</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Communications Type SM3</Name>
<Info>
<DefaultValue>4</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x1C12</Index>
<Name>Sync Manager 2 PDO Assignment</Name>
<Type>DT1C12</Type>
<BitSize>32</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>1</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>PDO Mapping</Name>
<Info>
<DefaultValue>#x1600</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x1C13</Index>
<Name>Sync Manager 3 PDO Assignment</Name>
<Type>DT1C13</Type>
<BitSize>32</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>1</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>PDO Mapping</Name>
<Info>
<DefaultValue>#x1A00</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x6000</Index>
<Name>Buttons</Name>
<Type>DT6000</Type>
<BitSize>24</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>1</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Button1</Name>
<Info>
<DefaultValue>0</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x7000</Index>
<Name>LEDs</Name>
<Type>DT7000</Type>
<BitSize>32</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>2</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>LED0</Name>
<Info>
<DefaultValue>0</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>LED1</Name>
<Info>
<DefaultValue>0</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
<Object>
<Index>#x8000</Index>
<Name>Parameters</Name>
<Type>DT8000</Type>
<BitSize>48</BitSize>
<Info>
<SubItem>
<Name>Number of Elements</Name>
<Info>
<DefaultValue>1</DefaultValue>
</Info>
</SubItem>
<SubItem>
<Name>Multiplier</Name>
<Info>
<DefaultValue>0</DefaultValue>
</Info>
</SubItem>
</Info>
<Flags>
<Access>ro</Access>
</Flags>
</Object>
</Objects>
</Dictionary>
</Profile>
<Fmmu>Outputs</Fmmu>
<Fmmu>Inputs</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="#x20" Enable="1" StartAddress="#x1180">Inputs</Sm>
<RxPdo Fixed="true" Mandatory="true" Sm="2">
<Index>#x1600</Index>
<Name>LEDs</Name>
<Entry>
<Index>#x7000</Index>
<SubIndex>1</SubIndex>
<BitLen>8</BitLen>
<Name>LED0</Name>
<DataType>USINT</DataType>
</Entry>
<Entry>
<Index>#x7000</Index>
<SubIndex>2</SubIndex>
<BitLen>8</BitLen>
<Name>LED1</Name>
<DataType>USINT</DataType>
</Entry>
</RxPdo>
<TxPdo Fixed="true" Mandatory="true" Sm="3">
<Index>#x1A00</Index>
<Name>Buttons</Name>
<Entry>
<Index>#x6000</Index>
<SubIndex>1</SubIndex>
<BitLen>8</BitLen>
<Name>Button1</Name>
<DataType>USINT</DataType>
</Entry>
</TxPdo>
<Mailbox DataLinkLayer="true">
<CoE CompleteAccess="false" PdoUpload="true" SdoInfo="true"/>
<FoE/>
</Mailbox>
<Eeprom>
<ByteSize>256</ByteSize>
<ConfigData>8002000000000000</ConfigData>
<BootStrap>0010800080108000</BootStrap>
</Eeprom>
</Device>
</Devices>
</Descriptions>
</EtherCATInfo>

View File

@ -0,0 +1,135 @@
#include "soes/esc_coe.h"
#include "utypes.h"
#include <stddef.h>
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[] = "Number of Elements";
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[] = "LEDs";
static const char acName1600_00[] = "Number of Elements";
static const char acName1600_01[] = "LED0";
static const char acName1600_02[] = "LED1";
static const char acName1A00[] = "Buttons";
static const char acName1A00_00[] = "Number of Elements";
static const char acName1A00_01[] = "Button1";
static const char acName1C00[] = "Sync Manager Communication Type";
static const char acName1C00_00[] = "Number of Elements";
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[] = "Number of Elements";
static const char acName1C12_01[] = "PDO Mapping";
static const char acName1C13[] = "Sync Manager 3 PDO Assignment";
static const char acName1C13_00[] = "Number of Elements";
static const char acName1C13_01[] = "PDO Mapping";
static const char acName6000[] = "Buttons";
static const char acName6000_00[] = "Number of Elements";
static const char acName6000_01[] = "Button1";
static const char acName7000[] = "LEDs";
static const char acName7000_00[] = "Number of Elements";
static const char acName7000_01[] = "LED0";
static const char acName7000_02[] = "LED1";
static const char acName8000[] = "Parameters";
static const char acName8000_00[] = "Number of Elements";
static const char acName8000_01[] = "Multiplier";
const _objd SDO1000[] =
{
{0x0, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1000_0, 0x01901389, NULL},
};
const _objd SDO1008[] =
{
{0x0, DTYPE_VISIBLE_STRING, 88, ATYPE_RO, acName1008_0, 0, "evb9252_dig"},
};
const _objd SDO1009[] =
{
{0x0, DTYPE_VISIBLE_STRING, 24, ATYPE_RO, acName1009_0, 0, "1.0"},
};
const _objd SDO100A[] =
{
{0x0, DTYPE_VISIBLE_STRING, 24, ATYPE_RO, acName100A_0, 0, "1.0"},
};
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, 1234, 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, 2, NULL},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_01, 0x70000108, NULL},
{0x02, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_02, 0x70000208, NULL},
};
const _objd SDO1A00[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1A00_00, 1, NULL},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_01, 0x60000108, 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[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName6000_00, 1, NULL},
{0x01, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName6000_01, 0, &Rb.Buttons.Button1},
};
const _objd SDO7000[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName7000_00, 2, NULL},
{0x01, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName7000_01, 0, &Wb.LEDs.LED0},
{0x02, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName7000_02, 0, &Wb.LEDs.LED1},
};
const _objd SDO8000[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName8000_00, 1, NULL},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RW, acName8000_01, 0, &Cb.Parameters.Multiplier},
};
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, 2, 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_RECORD, 1, 0, acName6000, SDO6000},
{0x7000, OTYPE_RECORD, 2, 0, acName7000, SDO7000},
{0x8000, OTYPE_RECORD, 1, 0, acName8000, SDO8000},
{0xffff, 0xff, 0xff, 0xff, NULL, NULL}
};

View File

@ -0,0 +1,47 @@
#ifndef __UTYPES_H__
#define __UTYPES_H__
#include <cc.h>
CC_PACKED_BEGIN
typedef struct
{
CC_PACKED_BEGIN
struct
{
uint8_t Button1;
} CC_PACKED Buttons;
CC_PACKED_END
} CC_PACKED _Rbuffer;
CC_PACKED_END
CC_PACKED_BEGIN
typedef struct
{
CC_PACKED_BEGIN
struct
{
uint8_t LED0;
uint8_t LED1;
} CC_PACKED LEDs;
CC_PACKED_END
} CC_PACKED _Wbuffer;
CC_PACKED_END
CC_PACKED_BEGIN
typedef struct
{
CC_PACKED_BEGIN
struct
{
uint32_t Multiplier;
} CC_PACKED Parameters;
CC_PACKED_END
} CC_PACKED _Cbuffer;
CC_PACKED_END
extern _Rbuffer Rb;
extern _Wbuffer Wb;
extern _Cbuffer Cb;
#endif /* __UTYPES_H__ */

View File

@ -43,6 +43,7 @@
#define ESCREG_ALCONTROL 0x0120
#define ESCREG_ALSTATUS 0x0130
#define ESCREG_ALERROR 0x0134
#define ESCREG_ALEVENT 0x0220
#define ESCREG_ALEVENT_SM_MASK 0x0310
#define ESCREG_ALEVENT_SMCHANGE 0x0010
#define ESCREG_ALEVENT_CONTROL 0x0001

View File

@ -0,0 +1,434 @@
/*
* SOES Simple Open EtherCAT Slave
*
* Copyright (C) 2007-2017 Arthur Ketels
* Copyright (C) 2012-2017 rt-labs.
*
* SOES is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* SOES is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* As a special exception, if other files instantiate templates or use macros
* or inline functions from this file, or you compile this file and link it
* with other works to produce a work based on this file, this file does not
* by itself cause the resulting work to be covered by the GNU General Public
* License. However the source code for this file must still be made available
* in accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work based on
* this file might be covered by the GNU General Public License.
*
* The EtherCAT Technology, the trade name and logo "EtherCAT" are the intellectual
* property of, and protected by Beckhoff Automation GmbH.
*/
/** \file
* \brief
* ESC hardware layer functions for LAN9252.
*
* Function to read and write commands to the ESC. Used to read/write ESC
* registers and memory.
*/
#include "utypes.h"
#include "esc.h"
#include <spi/spi.h>
#include <string.h>
#include <gpio.h>
#define ESC_CMD_SERIAL_WRITE 0x02
#define ESC_CMD_SERIAL_READ 0x03
#define ESC_CMD_FAST_READ 0x0B
#define ESC_CMD_RESET_SQI 0xFF
#define ESC_CMD_FAST_READ_DUMMY 1
#define ESC_CMD_ADDR_INC BIT(6)
#define ESC_PRAM_RD_FIFO_REG 0x000
#define ESC_PRAM_WR_FIFO_REG 0x020
#define ESC_PRAM_RD_ADDR_LEN_REG 0x308
#define ESC_PRAM_RD_CMD_REG 0x30C
#define ESC_PRAM_WR_ADDR_LEN_REG 0x310
#define ESC_PRAM_WR_CMD_REG 0x314
#define ESC_PRAM_CMD_BUSY BIT(31)
#define ESC_PRAM_CMD_ABORT BIT(30)
#define ESC_PRAM_CMD_CNT(x) ((x >> 8) & 0x1F)
#define ESC_PRAM_CMD_AVAIL BIT(0)
#define ESC_PRAM_SIZE(x) ((x) << 16)
#define ESC_PRAM_ADDR(x) ((x) << 0)
#define ESC_CSR_DATA_REG 0x300
#define ESC_CSR_CMD_REG 0x304
#define ESC_CSR_CMD_BUSY BIT(31)
#define ESC_CSR_CMD_READ (BIT(31) | BIT(30))
#define ESC_CSR_CMD_WRITE BIT(31)
#define ESC_CSR_CMD_SIZE(x) (x << 16)
#define ESC_RESET_CTRL_REG 0x1F8
#define ESC_RESET_CTRL_RST BIT(6)
static int lan9252 = -1;
/* lan9252 singel write */
static void lan9252_write_32 (uint16_t address, uint32_t val)
{
uint8_t data[7];
data[0] = ESC_CMD_SERIAL_WRITE;
data[1] = ((address >> 8) & 0xFF);
data[2] = (address & 0xFF);
data[3] = (val & 0xFF);
data[4] = ((val >> 8) & 0xFF);
data[5] = ((val >> 16) & 0xFF);
data[6] = ((val >> 24) & 0xFF);
/* Select device. */
spi_select (lan9252);
/* Write data */
write (lan9252, data, sizeof(data));
/* Un-select device. */
spi_unselect (lan9252);
}
/* lan9252 single read */
static uint32_t lan9252_read_32 (uint32_t address)
{
uint8_t data[4];
uint8_t result[4];
data[0] = ESC_CMD_FAST_READ;
data[1] = ((address >> 8) & 0xFF);
data[2] = (address & 0xFF);
data[3] = ESC_CMD_FAST_READ_DUMMY;
/* Select device. */
spi_select (lan9252);
/* Read data */
write (lan9252, data, sizeof(data));
read (lan9252, result, sizeof(result));
/* Un-select device. */
spi_unselect (lan9252);
return ((result[3] << 24) |
(result[2] << 16) |
(result[1] << 8) |
result[0]);
}
/* ESC read CSR function */
static void ESC_read_csr (uint16_t address, void *buf, uint16_t len)
{
uint32_t value;
value = (ESC_CSR_CMD_READ | ESC_CSR_CMD_SIZE(len) | address);
lan9252_write_32(ESC_CSR_CMD_REG, value);
do
{
value = lan9252_read_32(ESC_CSR_CMD_REG);
} while(value & ESC_CSR_CMD_BUSY);
value = lan9252_read_32(ESC_CSR_DATA_REG);
memcpy(buf, (uint8_t *)&value, len);
}
/* ESC write CSR function */
static void ESC_write_csr (uint16_t address, void *buf, uint16_t len)
{
uint32_t value;
memcpy((uint8_t*)&value, buf,len);
lan9252_write_32(ESC_CSR_DATA_REG, value);
value = (ESC_CSR_CMD_WRITE | ESC_CSR_CMD_SIZE(len) | address);
lan9252_write_32(ESC_CSR_CMD_REG, value);
do
{
value = lan9252_read_32(ESC_CSR_CMD_REG);
} while(value & ESC_CSR_CMD_BUSY);
}
/* ESC read process data ram function */
static void ESC_read_pram (uint16_t address, void *buf, uint16_t len)
{
uint32_t value;
uint8_t * temp_buf = buf;
uint8_t byte_offset = 0;
uint8_t fifo_cnt, first_byte_position, temp_len, data[4];
value = ESC_PRAM_CMD_ABORT;
lan9252_write_32(ESC_PRAM_RD_CMD_REG, value);
do
{
value = lan9252_read_32(ESC_PRAM_RD_CMD_REG);
}while(value & ESC_PRAM_CMD_BUSY);
value = ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address);
lan9252_write_32(ESC_PRAM_RD_ADDR_LEN_REG, value);
value = ESC_PRAM_CMD_BUSY;
lan9252_write_32(ESC_PRAM_RD_CMD_REG, value);
do
{
value = lan9252_read_32(ESC_PRAM_RD_CMD_REG);
}while((value & ESC_PRAM_CMD_AVAIL) == 0);
/* Fifo count */
fifo_cnt = ESC_PRAM_CMD_CNT(value);
/* Read first value from FIFO */
value = lan9252_read_32(ESC_PRAM_RD_FIFO_REG);
fifo_cnt--;
/* Find out first byte position and adjust the copy from that
* according to LAN9252 datasheet and MicroChip SDK code
*/
first_byte_position = (address & 0x03);
temp_len = ((4 - first_byte_position) > len) ? len : (4 - first_byte_position);
memcpy(temp_buf ,((uint8_t *)&value + first_byte_position), temp_len);
len -= temp_len;
byte_offset += temp_len;
/* Select device. */
spi_select (lan9252);
/* Send command and address for fifo read */
data[0] = ESC_CMD_FAST_READ;
data[1] = ((ESC_PRAM_RD_FIFO_REG >> 8) & 0xFF);
data[2] = (ESC_PRAM_RD_FIFO_REG & 0xFF);
data[3] = ESC_CMD_FAST_READ_DUMMY;
write (lan9252, data, sizeof(data));
/* Continue reading until we have read len */
while(len > 0)
{
temp_len = (len > 4) ? 4: len;
/* Always read 4 byte */
read (lan9252, (temp_buf + byte_offset), sizeof(uint32_t));
fifo_cnt--;
len -= temp_len;
byte_offset += temp_len;
}
/* Un-select device. */
spi_unselect (lan9252);
}
/* ESC write process data ram function */
static void ESC_write_pram (uint16_t address, void *buf, uint16_t len)
{
uint32_t value;
uint8_t * temp_buf = buf;
uint8_t byte_offset = 0;
uint8_t fifo_cnt, first_byte_position, temp_len, data[3];
value = ESC_PRAM_CMD_ABORT;
lan9252_write_32(ESC_PRAM_WR_CMD_REG, value);
do
{
value = lan9252_read_32(ESC_PRAM_WR_CMD_REG);
}while(value & ESC_PRAM_CMD_BUSY);
value = ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address);
lan9252_write_32(ESC_PRAM_WR_ADDR_LEN_REG, value);
value = ESC_PRAM_CMD_BUSY;
lan9252_write_32(ESC_PRAM_WR_CMD_REG, value);
do
{
value = lan9252_read_32(ESC_PRAM_WR_CMD_REG);
}while((value & ESC_PRAM_CMD_AVAIL) == 0);
/* Fifo count */
fifo_cnt = ESC_PRAM_CMD_CNT(value);
/* Find out first byte position and adjust the copy from that
* according to LAN9252 datasheet
*/
first_byte_position = (address & 0x03);
temp_len = ((4 - first_byte_position) > len) ? len : (4 - first_byte_position);
memcpy(((uint8_t *)&value + first_byte_position), temp_buf, temp_len);
/* Write first value from FIFO */
lan9252_write_32(ESC_PRAM_WR_FIFO_REG, value);
len -= temp_len;
byte_offset += temp_len;
fifo_cnt--;
/* Select device. */
spi_select (lan9252);
/* Send command and address for incrementing write */
data[0] = ESC_CMD_SERIAL_WRITE;
data[1] = ((ESC_PRAM_WR_FIFO_REG >> 8) & 0xFF);
data[2] = (ESC_PRAM_WR_FIFO_REG & 0xFF);
write (lan9252, data, sizeof(data));
/* Continue reading until we have read len */
while(len > 0)
{
temp_len = (len > 4) ? 4 : len;
value = 0;
memcpy((uint8_t *)&value, (temp_buf + byte_offset), temp_len);
/* Always write 4 byte */
write (lan9252, (void *)&value, sizeof(value));
fifo_cnt--;
len -= temp_len;
byte_offset += temp_len;
}
/* Un-select device. */
spi_unselect (lan9252);
}
/** 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)
{
/* Select Read function depending on address, process data ram or not */
if (address >= 0x1000)
{
ESC_read_pram(address, buf, len);
}
else
{
uint16_t size;
uint8_t *temp_buf = (uint8_t *)buf;
while(len > 0)
{
/* We write maximum 4 bytes at the time */
size = (len > 4) ? 4 : len;
/* Make size aligned to address according to LAN9252 datasheet
* Table 12-14 EtherCAT CSR Address VS size and MicroChip SDK code
*/
/* If we got an odd address size is 1 , 01b 11b is captured */
if(address & BIT(0))
{
size = 1;
}
/* If address 1xb and size != 1 and 3 , allow size 2 else size 1 */
else if (address & BIT(1))
{
size = (size & BIT(0)) ? 1 : 2;
}
/* size 3 not valid */
else if (size == 3)
{
size = 1;
}
/* else size is kept AS IS */
ESC_read_csr(address, temp_buf, size);
/* next address */
len -= size;
temp_buf += size;
address += size;
}
}
/* To mimic the ET1100 always providing AlEvent on every read or write */
ESC_read_csr(ESCREG_ALEVENT,(void *)&ESCvar.ALevent,sizeof(ESCvar.ALevent));
ESCvar.ALevent = etohs (ESCvar.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)
{
/* Select Write function depending on address, process data ram or not */
if (address >= 0x1000)
{
ESC_write_pram(address, buf, len);
}
else
{
uint16_t size;
uint8_t *temp_buf = (uint8_t *)buf;
while(len > 0)
{
/* We write maximum 4 bytes at the time */
size = (len > 4) ? 4 : len;
/* Make size aligned to address according to LAN9252 datasheet
* Table 12-14 EtherCAT CSR Address VS size and MicroChip SDK code
*/
/* If we got an odd address size is 1 , 01b 11b is captured */
if(address & BIT(0))
{
size = 1;
}
/* If address 1xb and size != 1 and 3 , allow size 2 else size 1 */
else if (address & BIT(1))
{
size = (size & BIT(0)) ? 1 : 2;
}
/* size 3 not valid */
else if (size == 3)
{
size = 1;
}
/* else size is kept AS IS */
ESC_write_csr(address, temp_buf, size);
/* next address */
len -= size;
temp_buf += size;
address += size;
}
}
/* To mimic the ET1x00 always providing AlEvent on every read or write */
ESC_read_csr(ESCREG_ALEVENT,(void *)&ESCvar.ALevent,sizeof(ESCvar.ALevent));
ESCvar.ALevent = etohs (ESCvar.ALevent);
}
/* Un-used due to evb-lan9252-digio not havning any possability to
* reset except over SPI.
*/
void ESC_reset (void)
{
}
void ESC_init (const void * arg)
{
uint32_t value;
const char * spi_name = (char *)arg;
lan9252 = open (spi_name, O_RDWR, 0);
/* Reset the ecat core here due to evb-lan9252-digio not having any GPIO
* for that purpose.
*/
lan9252_write_32(ESC_RESET_CTRL_REG,ESC_RESET_CTRL_RST);
do
{
value = lan9252_read_32(ESC_CSR_CMD_REG);
} while(value & ESC_RESET_CTRL_RST);
}