Compare commits

Invalid templates have been ignored

1 invalid template(s) found .github/PULL_REQUEST_TEMPLATE.md: 'about' is required

...

60 Commits

Author SHA1 Message Date
nakarlsson 8f3841e3ce
Merge pull request #180 from OpenEtherCATsociety/feature/improve_eeprom_reload_handling_al2
Improve emulated EEPROM reload handling
2024-04-09 16:15:44 +02:00
Andreas Karlsson fcd43fb2e6 Improve emulated EEPROM reload handling
Add variable to control if ESC support read size 4
or 8 Byte. Depends on ESC

Add variable and function to set user function to
perform emulated EEPROM reload.

Include custom reload sample snippets.
2024-04-09 14:03:31 +02:00
nakarlsson 66111d50fa
Merge pull request #176 from OpenEtherCATsociety/feature/add_sm_disabled_enabled_readback
Add readback that SM bit is set enabled/disabled
2024-03-27 11:09:03 +01:00
Andreas Karlsson 41438c4a33 Add readback that SM bit is set enabled/disabled
On PDI disable/enable, add polling readback that
it is set/cleared. Set 1 is delayed
until the end of a frame which is currently
processed, ET1100 datasheet.

This aligns the code base with SCC behavior.
2024-03-27 09:07:13 +01:00
nakarlsson 56124c2348
Merge pull request #170 from OpenEtherCATsociety/fix/reset_esc_repeat_ack
Sync local SM PDIreg with ESC PDIreg at Mbx start
2024-03-20 10:04:54 +01:00
Andreas Karlsson d04bed4666 Sync local SM PDIreg with ESC PDIreg at Mbx start
When starting mailbox service, write the value of
ECAT RepeatRequest to PDI RepeatAck. Otherwise
it is risk of a race condition when running
CTT and the repeat ack would hold the value
of previous repeat ack test.

The race condition occurs on slow targets
that doesn't handle the repeat request
fast enough. The resulting mailbox read
will come before the mailbox is emptied
on the SM changed event.

fixes
2024-03-20 08:26:25 +01:00
nakarlsson 05bf6c6726
Merge pull request #167 from OpenEtherCATsociety/fix/download_variable_using_CA
Fix padding of index 0 for object type variable
2024-02-05 16:38:10 +01:00
Andreas Karlsson 9525469a68 Fix padding of index 0 for object type variable
If object of type Variable return true bitsize
of subindex 0.

fixes #166
2024-02-05 09:36:04 +01:00
nakarlsson 3fe4511230
Merge pull request #152 from nakarlsson/fix/don_t_enable_debug_prints_by_default
Fix disable esc debug
2023-04-24 13:42:30 +02:00
Vijay Katoch e2f3fb7fd2 Fix disable esc debug 2023-04-24 13:39:34 +02:00
nakarlsson 6e70471e1b
Merge pull request #150 from nakarlsson/fix/Wconversion_generated_by_clang
Fix Wconversion issues for clang
2023-04-24 07:53:34 +02:00
Andreas Karlsson 70a1042188 Use inttypes print formatting macros
Use inttypes print formatting macros

Update DPRINT support for rt-kernel
2023-04-14 12:12:51 +02:00
Andreas Karlsson 2f4afb3230 Fix Wconversion issues for clang
Add explicit uint16_t cast for EoE header SET macros.
Used for SET of FrameInfo 1 and FrameInfo 2.

Increase datatype for offset used by EOE_HDR_FRAME_OFFSET_GET.

Change debug print formatting to %u for unsigned datatypes.
2023-04-14 12:12:22 +02:00
nakarlsson 5221cfbe76
Merge pull request #149 from nakarlsson/fix/warnings_generated_by_flag_Wconversion
Fix/warnings generated by flag wconversion
2023-03-29 12:13:27 +02:00
Andreas Karlsson 0d232899bb Enable Wconversion for Linux
Enable Wconversion for Linux for CI
to be used as regression.

Fix esc_hw.c warnings by adding explicit
typecasts. The code is based on Microchip
reference code so keep changes to a minimal.
2023-03-28 22:43:57 +02:00
Andreas Karlsson 3896a981ce Fix esc_foe Wconversion warnings
- make "size" variables not reflecting hardware or protocol
  uint32_t or size_t.

- add excplcit typecaste for uint8_t and uint16_t that need it
  due to integer promotion
2023-03-28 21:18:19 +02:00
Andreas Karlsson 45d390a014 Fix esc_eoe Wconversion warnings
- make "size" variables not reflecting hardware or protocol
  uint32_t.

- add excplcit typecaste for uint8_t and uint16_t that need it
  due to integer promotion

- split assignment using macros and bitwise operations to avoid
  implicit conversion and need of explicit conversion.
2023-03-28 21:18:14 +02:00
Andreas Karlsson f63bca476d Fix esc_coe Wconversion warnings
- make "size" variables not reflecting hardware or protocol
  uint32_t.

- change size_t to uint32_t to avoid conversion when compiling
  on x64

- add excplcit typecaste for uint8_t and uint16_t that need it
  due to integer promotion

- split assignment using macros and bitwise operations to avoid
  imlicit conversion and need of explicit conversion.

- add excplicit typecast to htoe MACROs
2023-03-28 21:17:59 +02:00
Andreas Karlsson d22277f4a5 Add typecast for bitwise operations of ESC
Add explicit typecasts for bitwise operations and
bitfields opeations of ESC.
2023-03-27 20:48:59 +02:00
Andreas Karlsson ac198e05b1 Add explicit typecast for ESC SM addressing
Add explicit typecast for uint16_t address
for ESC_read/WAC_write. The ESC RAM address
space is limited to 16Bit.
2023-03-27 20:48:59 +02:00
Andreas Karlsson 60e397aebc Change ESCvar member datatypes
* Align ESCvar.Alevent with ESC HW. Legacy it was 16-bit
      to be used with 2-byte mode SPI transfers that returned
      0x220-0x221.

* Increase size for fragments variables to avoid conversion
  warnings when counting mailbox data size. ESCvar.frags and
  ESCvar.fragsleft.
2023-03-27 20:48:59 +02:00
Andreas Karlsson 97472108e3 Add reference to objectlist in SM mappings
Rationale, users might need more info on what
object it is that is mapped. Having a reference to
objectlist enable the user to know what index it is
and got a reference to the entire object. The obj
only know what subindex it is.

fixes #137
2023-02-27 13:50:42 +01:00
Andreas Karlsson fd6dbdf188 Don't force packing of objd/objectlist stucts
objd/objectlist don't map to any EtheCAT protocol
headers, hence they don't need to be packed.

Pro and conns for packing or not.

Packed structs give optimized smaller size of ObjectDictionary.

Unpacked structs give optimized performance when iterating and
accessing processdata pointers.

Unpacked give more toolchain portable code.
2023-02-27 13:48:30 +01:00
Andreas Karlsson 3bb489469b Add support for CoE flags requried by MFC2020
Backup
Settings
RWop
RWpre_safe

(defined in ETG1000-6)

fixes #142
2023-02-27 13:48:30 +01:00
nakarlsson 8bb4350cd5
Merge pull request #140 from OpenEtherCATsociety/fix/bitpos_offset_in_mailbox_response
Add fix for bitpos2byteoffset
2022-11-28 16:49:51 +01:00
Andreas Karlsson fff8e22603 Add fix for bitpos2byteoffset
Can't use BITS2BYTE when calculating true bit offset
in a byte. Instead add a new macro that don't
round up to full byte size.

fixes #139
2022-11-26 13:11:34 +01:00
nakarlsson a7a017c26f
Merge pull request #120 from nakarlsson/master
Improve SM validation for input- ouput only slaves
2022-10-03 19:53:38 +02:00
nakarlsson ac0031aef5
Merge pull request #134 from m-dema/master
Exit eoe receive function if buffer is not valid
2022-09-27 18:23:37 +02:00
Andreas Karlsson 8ebb78ea10 Enable SM3 interrupt for input only slave
Enable SM3 interrupt if the slave only got
inputs.

On PREOP_TO_SAFEOP do an intial write to SM3,
otherwise the SM3 will never occur since there
is no data present to read.
2022-09-27 18:16:22 +02:00
m-dema 66b040a257
Exit eoe receive function if buffer is not valid
If buffer is invalid the call to the subsequent memcpy will corrupt memory
2022-09-23 17:04:42 +02:00
nakarlsson 8de160a851
Merge pull request #126 from fsugai/master
Fix: FOE_fwrite is unable to detect a failure if write_function fails to write on last data
2022-08-19 15:56:45 +02:00
Fumihito Sugai 35288ff3e7 Do not increment ncopied if failed writing 2022-08-19 22:47:45 +09:00
nakarlsson fc72fbeeec
Merge pull request #123 from konradhermsdorf/fix/rxpdo-handling-in-safeop
do not update output variables in SafeOp
2022-07-02 11:30:19 +02:00
Konrad Hermsdorf 254a6f807d do not update output variables in SafeOp
Just read SM data to reset SM Watchdog but do not update the output variables linked to the RxPDOs in SafeOp
2022-06-29 16:03:49 +02:00
andreas karlsson 48c80f5cae Impove SM validation for input- ouput only slaves
Re-add always verify SM length

Add validation of SM disabled, don't allow master
to activate or set a length if disabled.

Add validation of SM enabled, don't allow master
to set a length and de-activate.
2022-06-19 10:51:51 +02:00
nakarlsson acc59dd6b8
Merge pull request #119 from nakarlsson/master
Add support for input- or output only slaves
2022-06-15 20:58:33 +02:00
andreas karlsson 366c07f446 Add support for input- or output only slaves
Seperate validation of SM configuration that
depend on size of tx/rx pdo.

Add disable of SM3 when input only slave
reports error in OP.

Don't enable SM3 on start input if no inputs

Don't enable SM2 on start outputs if no
outputs

fix #112
fix #113
2022-06-15 20:50:31 +02:00
nakarlsson 6fc395e085
Merge pull request #117 from hefloryd/master
Declare rxpdo, txpdo as arrays
2022-06-02 14:16:26 +02:00
Hans-Erik Floryd d96f7cefef Declare rxpdo, txpdo as arrays
Rxpdo/txpdo were declared as external pointers if MAX_MAPPINGS2/3 were
0. However they must be declared as arrays for an external unit to be
able to use them as such.

Change-Id: I4bd547ae809ccfcb2dc1761f0f511f7e6088b712
2022-06-02 13:59:43 +02:00
nakarlsson fa0d6bf4d6
Merge pull request #116 from lrsdnlssn/master
Add support for Explicit Device Identification
2022-05-31 06:48:38 +02:00
Lars Danielsson 69b1049970 Add support for Explicit Device Identification
Change-Id: Idbf636f37c02923d251742cc5f49ff1579eaebc6
2022-05-30 15:51:20 +02:00
Hans-Erik Floryd 3c5af65be6
Merge pull request #109 from OpenEtherCATsociety/fix/download_segmented_completeaccess
Fix errornous segmented download CompleteAccess
2021-12-16 14:06:50 +01:00
andreas karlsson df0d169eef Fix errornous segmented download CompleteAccess
On the final segment the SDO shoud be written using the
pre-allocated buffer used to store segments during transfer.
When completed the pre-allocated buffer is written to the SDO.
This fix change to correct complete_access_subindex_loop
 - buffer, ESCvar.mbxdata
 - to use the lookup indexes for ESCVar.index -> nidx and
   ESCvar.subindex -> nsub.
2021-12-16 10:36:54 +01:00
nakarlsson 311977e47a
Merge pull request #105 from Joanle/fix-eeprom-command-def
correct eeprom command
2021-10-26 16:02:15 +02:00
Juan Leyva da33a714a1 Merge branch 'fix-eeprom-command-def' of https://github.com/Joanle/SOES into fix-eeprom-command-def 2021-10-26 08:50:04 -05:00
Juan Leyva cd12c0d156 correct eeprom command
change reload command to the correct value
2021-10-26 08:49:41 -05:00
nakarlsson ff6be22c80
Merge pull request #106 from hefloryd/master
Bump build platform and fix GCC9 warnings
2021-10-26 15:35:44 +02:00
Hans-Erik Floryd 2808e95668 Bump cmake version
Specifying a minimum cmake version 0f 2.8.4 triggers a warning with
never cmake, due to backwards compatibility issue. Bump to 2.8.12
which is the oldest version without the warning.
2021-10-26 09:36:04 +02:00
Hans-Erik Floryd 097477035d Fix address-of-packed-member warnings
GCC9 introduced an address-of-packed-member warning that triggers in
esc_coe.c. The issue is that a packed struct has an overall alignment
of 1, and taking the address of a member in a packed struct is not
guaranteed to have any particular alignment. However, in esc_coe these
structs are always overlayed on aligned memory so in practice there is
no problem.

Fix the problem by explicitly setting the minimum alignment for the
structs used in this manner. Also fix an instance where an unaligned
pointer was used but never dereferenced (by changing the type of the
pointer from uint32_t* to void*).
2021-10-26 09:36:04 +02:00
Hans-Erik Floryd 4d9da268be Bump build platform
Ubuntu 16.04 is now deprecated. Build using latest LTS.
2021-10-25 09:57:18 +02:00
Juan Leyva 5e94f0bb81 correct eeprom command
change reload command to the correct value
2021-10-15 23:32:20 -05:00
Hans-Erik Floryd 4549d0af9a
Merge pull request #103 from MechaMagpie/etherberry
Etherberry support
2021-09-06 16:44:29 +02:00
MechaMagpie 98a90d61ea Add simple demo for Raspberry Pi
Add a demo application for Raspberry Pi with a LAN9252-based EtherCat hat,
such as with the SG Electronics Systems EtherBerry.
2021-09-02 16:40:40 +02:00
iwoodsawyer b3e2a0a2c1 Add HAL for Raspberry Pi / LAN9252
Add support for EtherCAT slave HAT with LAN9252 chip (like EasyCAT or
EtherC/EtherBerry) for Raspberry Pi using the BCM2835 library.
2021-08-31 13:40:21 +02:00
nakarlsson 2fd5088fea
Merge pull request #100 from m-dema/patch-1
Fix inconsistent function name
2021-05-10 14:16:23 +02:00
m-dema c84a3ffb4d
Fix inconsistent function name
the function is different in header declaration (EOE_ecat_get_mac)
2021-05-06 17:05:46 +02:00
nakarlsson 1f24b72c5c
Merge pull request #99 from lrsdnlssn/master
Fix segmented download using complete access
2021-04-06 14:23:36 +02:00
Lars Danielsson e40d95cc1e Fix segmented download using complete access
Change-Id: If6060fb5bb1084c88c4159e2bcd38ba9b8eb3d40
2021-04-01 11:05:28 +02:00
nakarlsson f244ea522d
Merge pull request #98 from hefloryd/feature/gh-actions
Migrate to Github Actions
2021-02-17 16:45:26 +01:00
Hans-Erik Floryd 0d6f7de0e6 Migrate to Github Actions 2021-02-17 16:33:17 +01:00
31 changed files with 3459 additions and 304 deletions

23
.github/workflows/build.yml vendored 100644
View File

@ -0,0 +1,23 @@
name: build
on: [push, pull_request]
env:
BUILD_TYPE: Release
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Configure
shell: bash
run: |
cmake -E make_directory $GITHUB_WORKSPACE/build
cmake -B $GITHUB_WORKSPACE/build -S $GITHUB_WORKSPACE \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
- name: Build
shell: bash
run: |
cmake --build $GITHUB_WORKSPACE/build -j4

View File

@ -1,8 +0,0 @@
language: c
script:
- mkdir build
- pushd build
- cmake .. -DCMAKE_BUILD_TYPE=Release
- make
- popd

View File

@ -1,7 +1,7 @@
# CMakeLists files in this project can
# refer to the root source directory of the project as ${SOES_SOURCE_DIR} and
# to the root binary directory of the project as ${SOES_BINARY_DIR}.
cmake_minimum_required (VERSION 2.8.4)
cmake_minimum_required (VERSION 2.8.12)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
project (SOES)

View File

@ -1,6 +1,6 @@
Simple Open Source EtherCAT Slave
====
[![Build Status](https://travis-ci.org/OpenEtherCATsociety/SOES.svg?branch=master)](https://travis-ci.org/OpenEtherCATsociety/SOES)
[![Build Status](https://github.com/OpenEtherCATsociety/SOES/workflows/build/badge.svg?branch=master)](https://github.com/OpenEtherCATsociety/SOES/actions?workflow=build)
SOES (Simple OpenSource EtherCAT Slave Stack) is an opensource slave
stack that is very easy to use and provides a small footprint. It is a

View File

@ -0,0 +1,8 @@
add_executable (soes-demo
main.c
slave_objectlist.c
)
target_link_libraries(soes-demo LINK_PUBLIC soes bcm2835)
install (TARGETS soes-demo DESTINATION sbin)
install (PROGRAMS S60soes DESTINATION /etc/init.d)

View File

@ -0,0 +1,40 @@
#!/bin/sh
#
# soes Starts soes.
#
start() {
printf "Starting soes: "
/usr/sbin/soes-demo &
touch /var/lock/soes-demo
echo "OK"
}
stop() {
printf "Stopping soes: "
killall soes-demo
rm -f /var/lock/soes-demo
echo "OK"
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
restart
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?

View File

@ -0,0 +1,42 @@
#ifndef __ECAT_OPTIONS_H__
#define __ECAT_OPTIONS_H__
#define USE_FOE 1
#define USE_EOE 0
#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
#define MAX_MAPPINGS_SM2 7
#define MAX_MAPPINGS_SM3 7
#define MAX_RXPDO_SIZE 42
#define MAX_TXPDO_SIZE 42
#endif /* __ECAT_OPTIONS_H__ */

View File

@ -0,0 +1,108 @@
#include <stdio.h>
#include "ecat_slv.h"
#include "utypes.h"
#include <bcm2835.h>
/* Application variables */
_Objects Obj;
#define GPIO21 RPI_BPLUS_GPIO_J8_40
#define GPIO20 RPI_BPLUS_GPIO_J8_38
#define GPIO16 RPI_BPLUS_GPIO_J8_36
#define GPIO12 RPI_BPLUS_GPIO_J8_32
#define GPIO24 RPI_BPLUS_GPIO_J8_18
#define GPIO23 RPI_BPLUS_GPIO_J8_16
#define GPIO26 RPI_BPLUS_GPIO_J8_37
#define GPIO19 RPI_BPLUS_GPIO_J8_35
#define GPIO13 RPI_BPLUS_GPIO_J8_33
#define GPIO06 RPI_BPLUS_GPIO_J8_31
#define GPIO05 RPI_BPLUS_GPIO_J8_29
#define GPIO22 RPI_BPLUS_GPIO_J8_15
void cb_get_inputs (void)
{
// Assume LEDs connected to 3.3v
bcm2835_gpio_write(GPIO21, (Obj.LEDs.LED0 ? LOW : HIGH));
bcm2835_gpio_write(GPIO20, (Obj.LEDs.LED1 ? LOW : HIGH));
bcm2835_gpio_write(GPIO16, (Obj.LEDs.LED2 ? LOW : HIGH));
bcm2835_gpio_write(GPIO12, (Obj.LEDs.LED3 ? LOW : HIGH));
bcm2835_gpio_write(GPIO24, (Obj.LEDs.LED4 ? LOW : HIGH));
bcm2835_gpio_write(GPIO23, (Obj.LEDs.LED5 ? LOW : HIGH));
}
void cb_set_outputs (void)
{
// Assume Buttons connected to 3.3v
Obj.Buttons.Button0 = bcm2835_gpio_lev(GPIO26);
Obj.Buttons.Button0 = bcm2835_gpio_lev(GPIO19);
Obj.Buttons.Button0 = bcm2835_gpio_lev(GPIO13);
Obj.Buttons.Button0 = bcm2835_gpio_lev(GPIO06);
Obj.Buttons.Button0 = bcm2835_gpio_lev(GPIO05);
Obj.Buttons.Button0 = bcm2835_gpio_lev(GPIO22);
}
void GPIO_init (void)
{
bcm2835_init();
// Assume LEDs connected to 3.3v side of header
bcm2835_gpio_fsel(GPIO21, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(GPIO20, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(GPIO16, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(GPIO12, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(GPIO24, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(GPIO23, BCM2835_GPIO_FSEL_OUTP);
// Assume buttons connected to 5v side of header
// Do not bridge to 5v, the ports might burn
bcm2835_gpio_fsel(GPIO26, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(GPIO19, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(GPIO13, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(GPIO06, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(GPIO05, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(GPIO22, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_set_pud(GPIO26, BCM2835_GPIO_PUD_DOWN);
bcm2835_gpio_set_pud(GPIO19, BCM2835_GPIO_PUD_DOWN);
bcm2835_gpio_set_pud(GPIO13, BCM2835_GPIO_PUD_DOWN);
bcm2835_gpio_set_pud(GPIO06, BCM2835_GPIO_PUD_DOWN);
bcm2835_gpio_set_pud(GPIO05, BCM2835_GPIO_PUD_DOWN);
bcm2835_gpio_set_pud(GPIO22, BCM2835_GPIO_PUD_DOWN);
}
int main_run (void * arg)
{
static esc_cfg_t config =
{
.user_arg = "rpi3,cs0",
.use_interrupt = 0,
.watchdog_cnt = 150,
.set_defaults_hook = NULL,
.pre_state_change_hook = NULL,
.post_state_change_hook = NULL,
.application_hook = NULL,
.safeoutput_override = NULL,
.pre_object_download_hook = NULL,
.post_object_download_hook = NULL,
.rxpdo_override = NULL,
.txpdo_override = NULL,
.esc_hw_interrupt_enable = NULL,
.esc_hw_interrupt_disable = NULL,
.esc_hw_eep_handler = NULL,
.esc_check_dc_handler = NULL,
};
printf ("Hello Main\n");
GPIO_init();
ecat_slv_init (&config);
while (1)
{
ecat_slv();
}
return 0;
}
int main (void)
{
printf ("Hello Main\n");
main_run (NULL);
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,532 @@
<?xml version="1.0" encoding="UTF-8"?>
<Slave xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="com.rtlabs.emf.esx" fileVersion="2" id="evb9252_dig" productCode="1234" additionalInfo="0x0190">
<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 Lan9252="true">
<ConfigData>8002000000000000</ConfigData>
<BootStrap>0010800080108000</BootStrap>
</Eeprom>
<Dictionary>
<Item Managed="true">
<Index>0x1000</Index>
<Name>Device Type</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x01901389</DefaultValue>
</Item>
<Item Managed="true">
<Index>0x1008</Index>
<Name>Device Name</Name>
<DataType>VISIBLE_STRING</DataType>
<DefaultValue>evb9252_dig</DefaultValue>
<Length>11</Length>
</Item>
<Item Managed="false">
<Index>0x1009</Index>
<Name>Hardware Version</Name>
<DataType>VISIBLE_STRING</DataType>
<DefaultValue>1.0</DefaultValue>
</Item>
<Item Managed="false">
<Index>0x100A</Index>
<Name>Software Version</Name>
<DataType>VISIBLE_STRING</DataType>
<DefaultValue>1.0</DefaultValue>
</Item>
<Item Managed="true">
<Index>0x1018</Index>
<Name>Identity Object</Name>
<DataType>RECORD</DataType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>4</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Name>Vendor ID</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x1337</DefaultValue>
</SubItem>
<SubItem>
<Index>0x02</Index>
<Name>Product Code</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>1234</DefaultValue>
</SubItem>
<SubItem>
<Index>0x03</Index>
<Name>Revision Number</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0</DefaultValue>
</SubItem>
<SubItem>
<Index>0x04</Index>
<Name>Serial Number</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x00000000</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x1600</Index>
<Name>LEDs</Name>
<DataType>RECORD</DataType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>9</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Name>LED0</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000108</DefaultValue>
</SubItem>
<SubItem>
<Index>0x02</Index>
<Name>LED1</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000208</DefaultValue>
</SubItem>
<SubItem>
<Index>0x03</Index>
<Name>New Member</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000301</DefaultValue>
</SubItem>
<SubItem>
<Index>0x04</Index>
<Name>New Member</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000401</DefaultValue>
</SubItem>
<SubItem>
<Index>0x05</Index>
<Name>New Member</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000501</DefaultValue>
</SubItem>
<SubItem>
<Index>0x06</Index>
<Name>New Member</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000601</DefaultValue>
</SubItem>
<SubItem>
<Index>0x07</Index>
<Name>New Member</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000701</DefaultValue>
</SubItem>
<SubItem>
<Index>0x08</Index>
<Name>New Member</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x70000801</DefaultValue>
</SubItem>
<SubItem>
<Index>0x09</Index>
<Name>Padding 9</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x00000002</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x1A00</Index>
<Name>Buttons</Name>
<DataType>RECORD</DataType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Name>Button1</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0x60000108</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x1C00</Index>
<Name>Sync Manager Communication Type</Name>
<DataType>ARRAY</DataType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>4</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Name>Communications Type SM0</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Index>0x02</Index>
<Name>Communications Type SM1</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>2</DefaultValue>
</SubItem>
<SubItem>
<Index>0x03</Index>
<Name>Communications Type SM2</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>3</DefaultValue>
</SubItem>
<SubItem>
<Index>0x04</Index>
<Name>Communications Type SM3</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>4</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x1C12</Index>
<Name>Sync Manager 2 PDO Assignment</Name>
<DataType>ARRAY</DataType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Name>PDO Mapping</Name>
<DataType>UNSIGNED16</DataType>
<DefaultValue>0x1600</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x1C13</Index>
<Name>Sync Manager 3 PDO Assignment</Name>
<DataType>ARRAY</DataType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Name>PDO Mapping</Name>
<DataType>UNSIGNED16</DataType>
<DefaultValue>0x1A00</DefaultValue>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x6000</Index>
<Name>Buttons</Name>
<DataType>RECORD</DataType>
<Variable>Buttons</Variable>
<VariableType>Input</VariableType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Access>RO</Access>
<Name>Button1</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>0</DefaultValue>
<Variable>Button1</Variable>
<VariableType>Input</VariableType>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x7000</Index>
<Name>LEDs</Name>
<DataType>RECORD</DataType>
<Variable>LEDs</Variable>
<VariableType>Output</VariableType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>8</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Access>RO</Access>
<Name>LED0</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>0</DefaultValue>
<Variable>LED0</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Index>0x02</Index>
<Access>RO</Access>
<Name>LED1</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>0</DefaultValue>
<Variable>LED1</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Index>0x03</Index>
<Access>RO</Access>
<Name>New Member</Name>
<DataType>BOOLEAN</DataType>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
<Variable>New_Member</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Index>0x04</Index>
<Access>RO</Access>
<Name>New Member</Name>
<DataType>BOOLEAN</DataType>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
<Variable>New_Member</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Index>0x05</Index>
<Access>RO</Access>
<Name>New Member</Name>
<DataType>BOOLEAN</DataType>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
<Variable>New_Member</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Index>0x06</Index>
<Access>RO</Access>
<Name>New Member</Name>
<DataType>BOOLEAN</DataType>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
<Variable>New_Member</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Index>0x07</Index>
<Access>RO</Access>
<Name>New Member</Name>
<DataType>BOOLEAN</DataType>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
<Variable>New_Member</Variable>
<VariableType>Output</VariableType>
</SubItem>
<SubItem>
<Index>0x08</Index>
<Access>RO</Access>
<Name>New Member</Name>
<DataType>BOOLEAN</DataType>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
<Variable>New_Member</Variable>
<VariableType>Output</VariableType>
</SubItem>
</Item>
<Item Managed="true">
<Index>0x8000</Index>
<Name>Parameters</Name>
<DataType>RECORD</DataType>
<Variable>Parameters</Variable>
<VariableType>Parameter</VariableType>
<SubItem>
<Index>0x00</Index>
<Name>Max SubIndex</Name>
<DataType>UNSIGNED8</DataType>
<DefaultValue>1</DefaultValue>
</SubItem>
<SubItem>
<Index>0x01</Index>
<Access>RW</Access>
<Name>Multiplier</Name>
<DataType>UNSIGNED32</DataType>
<DefaultValue>0</DefaultValue>
<Variable>Multiplier</Variable>
<VariableType>Parameter</VariableType>
</SubItem>
</Item>
</Dictionary>
<SmAssignment>
<Index>0x1C12</Index>
<Entry>
<Index>0x01</Index>
<AssignedPdo>0x1600</AssignedPdo>
</Entry>
</SmAssignment>
<SmAssignment>
<Index>0x1C13</Index>
<Entry>
<Index>0x01</Index>
<AssignedPdo>0x1A00</AssignedPdo>
</Entry>
</SmAssignment>
<RxPdo>
<Index>0x1600</Index>
<Name>LEDs</Name>
<Entry>
<Index>0x1</Index>
<MappedIndex>0x7000</MappedIndex>
<MappedSubIndex>0x01</MappedSubIndex>
<Variable>LED0</Variable>
</Entry>
<Entry>
<Index>0x2</Index>
<MappedIndex>0x7000</MappedIndex>
<MappedSubIndex>0x02</MappedSubIndex>
<Variable>LED1</Variable>
</Entry>
<Entry>
<Index>0x3</Index>
<MappedIndex>0x7000</MappedIndex>
<MappedSubIndex>0x03</MappedSubIndex>
<Variable>LED2</Variable>
</Entry>
<Entry>
<Index>0x4</Index>
<MappedIndex>0x7000</MappedIndex>
<MappedSubIndex>0x04</MappedSubIndex>
<Variable>LED3</Variable>
</Entry>
<Entry>
<Index>0x5</Index>
<MappedIndex>0x7000</MappedIndex>
<MappedSubIndex>0x05</MappedSubIndex>
<Variable>LED4</Variable>
</Entry>
<Entry>
<Index>0x6</Index>
<MappedIndex>0x7000</MappedIndex>
<MappedSubIndex>0x06</MappedSubIndex>
<Variable>LED5</Variable>
</Entry>
<Entry padBits="2">
<Index>0x09</Index>
</Entry>
</RxPdo>
<TxPdo>
<Index>0x1A00</Index>
<Name>Buttons</Name>
<Entry>
<Index>0x1</Index>
<MappedIndex>0x6000</MappedIndex>
<MappedSubIndex>0x01</MappedSubIndex>
<Variable>Button0</Variable>
</Entry>
</TxPdo>
<Input>
<Index>0x6000</Index>
<Name>Buttons</Name>
<ObjectType>RECORD</ObjectType>
<Member>
<Index>0x01</Index>
<Access>RO</Access>
<Name>Button0</Name>
<Type>BOOLEAN</Type>
<DefaultValue>0</DefaultValue>
<PdoMapping>TX</PdoMapping>
</Member>
<Member>
<Index>0x02</Index>
<Name>Button1</Name>
<PdoMapping>TX</PdoMapping>
</Member>
<Member>
<Index>0x03</Index>
<Name>Button2</Name>
<PdoMapping>TX</PdoMapping>
</Member>
<Member>
<Index>0x04</Index>
<Name>Button3</Name>
<PdoMapping>TX</PdoMapping>
</Member>
<Member>
<Index>0x05</Index>
<Name>Button4</Name>
<PdoMapping>TX</PdoMapping>
</Member>
<Member>
<Index>0x06</Index>
<Name>Button5</Name>
<PdoMapping>TX</PdoMapping>
</Member>
</Input>
<Output>
<Index>0x7000</Index>
<Name>LEDs</Name>
<ObjectType>RECORD</ObjectType>
<Member>
<Index>0x01</Index>
<Access>RO</Access>
<Name>LED0</Name>
<Type>BOOLEAN</Type>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
</Member>
<Member>
<Index>0x02</Index>
<Access>RO</Access>
<Name>LED1</Name>
<Type>BOOLEAN</Type>
<DefaultValue>0</DefaultValue>
<PdoMapping>RX</PdoMapping>
</Member>
<Member>
<Index>0x03</Index>
<Name>LED2</Name>
<PdoMapping>RX</PdoMapping>
</Member>
<Member>
<Index>0x04</Index>
<Name>LED3</Name>
<PdoMapping>RX</PdoMapping>
</Member>
<Member>
<Index>0x05</Index>
<Name>LED4</Name>
<PdoMapping>RX</PdoMapping>
</Member>
<Member>
<Index>0x06</Index>
<Name>LED5</Name>
<PdoMapping>RX</PdoMapping>
</Member>
</Output>
<Parameter>
<Index>0x8000</Index>
<Name>Parameters</Name>
<ObjectType>RECORD</ObjectType>
<Member>
<Index>0x01</Index>
<Access>RW</Access>
<Name>Multiplier</Name>
<Type>UNSIGNED32</Type>
<DefaultValue>0</DefaultValue>
</Member>
</Parameter>
</Slave>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
#include "esc_coe.h"
#include "utypes.h"
#include <stddef.h>
#ifndef HW_REV
#define HW_REV "1.0"
#endif
#ifndef SW_REV
#define SW_REV "1.0"
#endif
static const char acName1000[] = "Device Type";
static const char acName1008[] = "Device Name";
static const char acName1009[] = "Hardware Version";
static const char acName100A[] = "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[] = "LEDs";
static const char acName1600_00[] = "Max SubIndex";
static const char acName1600_01[] = "LED0";
static const char acName1600_02[] = "LED1";
static const char acName1600_03[] = "LED2";
static const char acName1600_04[] = "LED3";
static const char acName1600_05[] = "LED4";
static const char acName1600_06[] = "LED5";
static const char acName1600_07[] = "Padding 7";
static const char acName1A00[] = "Buttons";
static const char acName1A00_00[] = "Max SubIndex";
static const char acName1A00_01[] = "Button0";
static const char acName1A00_02[] = "Button1";
static const char acName1A00_03[] = "Button2";
static const char acName1A00_04[] = "Button3";
static const char acName1A00_05[] = "Button4";
static const char acName1A00_06[] = "Button5";
static const char acName1A00_07[] = "Padding 7";
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[] = "Buttons";
static const char acName6000_00[] = "Max SubIndex";
static const char acName6000_01[] = "Button0";
static const char acName6000_02[] = "Button1";
static const char acName6000_03[] = "Button2";
static const char acName6000_04[] = "Button3";
static const char acName6000_05[] = "Button4";
static const char acName6000_06[] = "Button5";
static const char acName7000[] = "LEDs";
static const char acName7000_00[] = "Max SubIndex";
static const char acName7000_01[] = "LED0";
static const char acName7000_02[] = "LED1";
static const char acName7000_03[] = "LED2";
static const char acName7000_04[] = "LED3";
static const char acName7000_05[] = "LED4";
static const char acName7000_06[] = "LED5";
static const char acName8000[] = "Parameters";
static const char acName8000_00[] = "Max SubIndex";
static const char acName8000_01[] = "Multiplier";
const _objd SDO1000[] =
{
{0x0, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1000, 0x01901389, NULL},
};
const _objd SDO1008[] =
{
{0x0, DTYPE_VISIBLE_STRING, 88, ATYPE_RO, acName1008, 0, "evb9252_dig"},
};
const _objd SDO1009[] =
{
{0x0, DTYPE_VISIBLE_STRING, 0, ATYPE_RO, acName1009, 0, HW_REV},
};
const _objd SDO100A[] =
{
{0x0, DTYPE_VISIBLE_STRING, 0, ATYPE_RO, acName100A, 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, 1234, NULL},
{0x03, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_03, 0, NULL},
{0x04, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1018_04, 0x00000000, &Obj.serial},
};
const _objd SDO1600[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1600_00, 7, NULL},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_01, 0x70000101, NULL},
{0x02, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_02, 0x70000201, NULL},
{0x03, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_03, 0x70000301, NULL},
{0x04, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_04, 0x70000401, NULL},
{0x05, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_05, 0x70000501, NULL},
{0x06, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_06, 0x70000601, NULL},
{0x07, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1600_07, 0x00000002, NULL},
};
const _objd SDO1A00[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1A00_00, 7, NULL},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_01, 0x60000101, NULL},
{0x02, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_02, 0x60000201, NULL},
{0x03, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_03, 0x60000301, NULL},
{0x04, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_04, 0x60000401, NULL},
{0x05, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_05, 0x60000501, NULL},
{0x06, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_06, 0x60000601, NULL},
{0x07, DTYPE_UNSIGNED32, 32, ATYPE_RO, acName1A00_07, 0x00000002, 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, 6, NULL},
{0x01, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_TXPDO, acName6000_01, 0, &Obj.Buttons.Button0},
{0x02, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_TXPDO, acName6000_02, 0, &Obj.Buttons.Button1},
{0x03, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_TXPDO, acName6000_03, 0, &Obj.Buttons.Button2},
{0x04, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_TXPDO, acName6000_04, 0, &Obj.Buttons.Button3},
{0x05, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_TXPDO, acName6000_05, 0, &Obj.Buttons.Button4},
{0x06, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_TXPDO, acName6000_06, 0, &Obj.Buttons.Button5},
};
const _objd SDO7000[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName7000_00, 6, NULL},
{0x01, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_RXPDO, acName7000_01, 0, &Obj.LEDs.LED0},
{0x02, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_RXPDO, acName7000_02, 0, &Obj.LEDs.LED1},
{0x03, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_RXPDO, acName7000_03, 0, &Obj.LEDs.LED2},
{0x04, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_RXPDO, acName7000_04, 0, &Obj.LEDs.LED3},
{0x05, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_RXPDO, acName7000_05, 0, &Obj.LEDs.LED4},
{0x06, DTYPE_BOOLEAN, 1, ATYPE_RO | ATYPE_RXPDO, acName7000_06, 0, &Obj.LEDs.LED5},
};
const _objd SDO8000[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName8000_00, 1, NULL},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RW, acName8000_01, 0, &Obj.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, 7, 0, acName1600, SDO1600},
{0x1A00, OTYPE_RECORD, 7, 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, 6, 0, acName6000, SDO6000},
{0x7000, OTYPE_RECORD, 6, 0, acName7000, SDO7000},
{0x8000, OTYPE_RECORD, 1, 0, acName8000, SDO8000},
{0xffff, 0xff, 0xff, 0xff, NULL, NULL}
};

View File

@ -0,0 +1,49 @@
#ifndef __UTYPES_H__
#define __UTYPES_H__
#include "cc.h"
/* Object dictionary storage */
typedef struct
{
/* Identity */
uint32_t serial;
/* Inputs */
struct
{
uint8_t Button0;
uint8_t Button1;
uint8_t Button2;
uint8_t Button3;
uint8_t Button4;
uint8_t Button5;
} Buttons;
/* Outputs */
struct
{
uint8_t LED0;
uint8_t LED1;
uint8_t LED2;
uint8_t LED3;
uint8_t LED4;
uint8_t LED5;
} LEDs;
/* Parameters */
struct
{
uint32_t Multiplier;
} Parameters;
} _Objects;
extern _Objects Obj;
#endif /* __UTYPES_H__ */

View File

@ -38,6 +38,13 @@ void cb_state_change (uint8_t * as, uint8_t * an)
/* Enable watchdog interrupt */
ESC_ALeventmaskwrite (ESC_ALeventmaskread() | ESCREG_ALEVENT_WD);
}
else if (*as == PREOP_TO_SAFEOP)
{
/* Write initial input data requried if an input only slave,
* otherwise the SM3 will never occur.
*/
DIG_process (DIG_PROCESS_INPUTS_FLAG);
}
}
/* Setup of DC */
@ -70,6 +77,7 @@ int main (void)
.esc_hw_interrupt_disable = ESC_interrupt_disable,
.esc_hw_eep_handler = ESC_eep_handler,
.esc_check_dc_handler = dc_checker
.get_device_id = NULL
};
rprintf ("Hello world\n");

View File

@ -1,14 +1,20 @@
set(SOES_DEMO applications/linux_lan9252demo)
if(RPI_VARIANT)
set (SOES_DEMO applications/raspberry_lan9252demo)
set(HAL_SOURCES
${SOES_SOURCE_DIR}/soes/hal/raspberrypi-lan9252/esc_hw.c
${SOES_SOURCE_DIR}/soes/hal/raspberrypi-lan9252/esc_hw.h
)
else()
set(SOES_DEMO applications/linux_lan9252demo)
set(HAL_SOURCES
${SOES_SOURCE_DIR}/soes/hal/linux-lan9252/esc_hw.c
)
endif()
include_directories(
${SOES_SOURCE_DIR}/soes/include/sys/gcc
${SOES_SOURCE_DIR}/${SOES_DEMO}
)
set(HAL_SOURCES
${SOES_SOURCE_DIR}/soes/hal/linux-lan9252/esc_hw.c
)
# Common compile flags
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Werror)
add_compile_options(-Wall -Wextra -Wconversion -Wno-unused-parameter -Werror)

View File

@ -25,13 +25,13 @@ static volatile int watchdog;
#if MAX_MAPPINGS_SM2 > 0
static uint8_t rxpdo[MAX_RXPDO_SIZE] __attribute__((aligned (8)));
#else
extern uint8_t * rxpdo;
extern uint8_t rxpdo[];
#endif
#if MAX_MAPPINGS_SM3 > 0
static uint8_t txpdo[MAX_TXPDO_SIZE] __attribute__((aligned (8)));
#else
extern uint8_t * txpdo;
extern uint8_t txpdo[];
#endif
/** Function to pre-qualify the incoming SDO download.
@ -202,7 +202,8 @@ void DIG_process (uint8_t flags)
}
if ((CC_ATOMIC_GET(watchdog) <= 0) &&
((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0))
((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0) &&
(ESCvar.ESC_SM2_sml > 0))
{
DPRINT("DIG_process watchdog expired\n");
ESC_ALstatusgotoerror((ESCsafeop | ESCerror), ALERR_WATCHDOG);
@ -226,7 +227,7 @@ void DIG_process (uint8_t flags)
}
else if (ESCvar.ALevent & ESCREG_ALEVENT_SM2)
{
RXPDO_update();
ESC_read (ESC_SM2_sma, rxpdo, ESCvar.ESC_SM2_sml);
}
}

View File

@ -62,7 +62,7 @@ void ESC_ALstatusgotoerror (uint8_t status, uint16_t errornumber)
as = ESCvar.ALstatus & ESCREG_AL_ERRACKMASK;
an = as;
/* Set the state transition, new state in high bits and old in bits */
as = ((status & ESCREG_AL_ERRACKMASK) << 4) | (as & 0x0f);
as = (uint8_t)(((status & ESCREG_AL_ERRACKMASK) << 4) | (as & 0x0f));
/* Call post state change hook case it have been configured */
if (ESCvar.pre_state_change_hook != NULL)
{
@ -136,7 +136,7 @@ uint32_t ESC_ALeventread (void)
void ESC_SMack (uint8_t n)
{
uint8_t dummy;
ESC_read (ESCREG_SM0ACTIVATE + (n << 3), &dummy, 1);
ESC_read ((uint16_t)(ESCREG_SM0ACTIVATE + (n << 3)), &dummy, 1);
}
/** Read SM Status register 0x805(+ offset to SyncManager n) and save the
@ -148,7 +148,7 @@ void ESC_SMstatus (uint8_t n)
{
_ESCsm2 *sm;
sm = (_ESCsm2 *)&ESCvar.SM[n];
ESC_read (ESCREG_SM0STATUS + (n << 3), &(sm->Status), 1);
ESC_read ((uint16_t)(ESCREG_SM0STATUS + (n << 3)), &(sm->Status), 1);
}
/** Write ESCvar.SM[n] data to ESC PDI control register 0x807(+ offset to SyncManager n).
@ -159,7 +159,18 @@ void ESC_SMwritepdi (uint8_t n)
{
_ESCsm2 *sm;
sm = (_ESCsm2 *)&ESCvar.SM[n];
ESC_write (ESCREG_SM0PDI + (n << 3), &(sm->ActPDI), 1);
ESC_write ((uint16_t)(ESCREG_SM0PDI + (n << 3)), &(sm->ActPDI), 1);
}
/** Read ESC PDI control register 0x807(+ offset to SyncManager n) to ESCvar.SM[n] data.
*
* @param[in] n = Read from Sync Manager no. n
*/
void ESC_SMreadpdi (uint8_t n)
{
_ESCsm2* sm;
sm = (_ESCsm2*)&ESCvar.SM[n];
ESC_read ((uint16_t)(ESCREG_SM0PDI + (n << 3)), &(sm->ActPDI), 1);
}
/** Write 0 to Bit0 in SM PDI control register 0x807(+ offset to SyncManager n) to Activate the Sync Manager n.
@ -170,8 +181,13 @@ void ESC_SMenable (uint8_t n)
{
_ESCsm2 *sm;
sm = (_ESCsm2 *)&ESCvar.SM[n];
sm->ActPDI &= ~ESCREG_SMENABLE_BIT;
sm->ActPDI &= (uint8_t)~ESCREG_SMENABLE_BIT;
ESC_SMwritepdi (n);
/* Read back wait until enabled */
do
{
ESC_SMreadpdi (n);
} while ((sm->ActPDI & ESCREG_SMENABLE_BIT) == 1);
}
/** Write 1 to Bit0 in SM PDI control register 0x807(+ offset to SyncManager n) to De-activte the Sync Manager n.
*
@ -183,6 +199,11 @@ void ESC_SMdisable (uint8_t n)
sm = (_ESCsm2 *)&ESCvar.SM[n];
sm->ActPDI |= ESCREG_SMENABLE_BIT;
ESC_SMwritepdi (n);
/* Read back wait until disabled */
do
{
ESC_SMreadpdi (n);
} while ((sm->ActPDI & ESCREG_SMENABLE_BIT) == 0);
}
/** Read Configured Station Address register 0x010 assigned by the Master.
*
@ -321,7 +342,6 @@ uint8_t ESC_startmbx (uint8_t state)
ESCvar.activemb0 = &ESCvar.mb[0];
ESCvar.activemb1 = &ESCvar.mb[1];
ESC_SMenable (0);
ESC_SMenable (1);
ESC_SMstatus (0);
@ -334,6 +354,8 @@ uint8_t ESC_startmbx (uint8_t state)
else
{
ESCvar.toggle = ESCvar.SM[1].ECrep; //sync repeat request toggle state
ESCvar.SM[1].PDIrep = ESCvar.toggle & 0x1U;
ESC_SMwritepdi (1);
ESCvar.MBXrun = 1;
}
return state;
@ -367,6 +389,8 @@ uint8_t ESC_startmbxboot (uint8_t state)
else
{
ESCvar.toggle = ESCvar.SM[1].ECrep; //sync repeat request toggle state
ESCvar.SM[1].PDIrep = ESCvar.toggle & 0x1U;
ESC_SMwritepdi (1);
ESCvar.MBXrun = 1;
}
return state;
@ -414,9 +438,9 @@ void ESC_readmbx (void)
if (length > (ESC_MBX0_sml - ESC_MBXHSIZE))
{
length = ESC_MBX0_sml - ESC_MBXHSIZE;
length = (uint16_t)(ESC_MBX0_sml - ESC_MBXHSIZE);
}
ESC_read (ESC_MBX0_sma + ESC_MBXHSIZE, MB->b, length);
ESC_read ((uint16_t)(ESC_MBX0_sma + ESC_MBXHSIZE), MB->b, length);
if (length + ESC_MBXHSIZE < ESC_MBX0_sml)
{
ESC_read (ESC_MBX0_sme, &length, 1);
@ -439,9 +463,9 @@ void ESC_writembx (uint8_t n)
if (length > (ESC_MBX1_sml - ESC_MBXHSIZE))
{
length = ESC_MBX1_sml - ESC_MBXHSIZE;
length = (uint16_t)(ESC_MBX1_sml - ESC_MBXHSIZE);
}
ESC_write (ESC_MBX1_sma, MBh, ESC_MBXHSIZE + length);
ESC_write (ESC_MBX1_sma, MBh, (uint16_t)(ESC_MBXHSIZE + length));
if (length + ESC_MBXHSIZE < ESC_MBX1_sml)
{
ESC_write (ESC_MBX1_sme, &dummy, 1);
@ -487,7 +511,7 @@ uint8_t ESC_claimbuffer (void)
MBh->address = htoes (0x0000); // destination is master
MBh->channel = 0;
MBh->priority = 0;
MBh->mbxcnt = ESCvar.mbxcnt;
MBh->mbxcnt = ESCvar.mbxcnt & 0xFU;
ESCvar.txcue++;
}
return n;
@ -601,7 +625,7 @@ uint8_t ESC_mbxprocess (void)
ESC_writembx (ESCvar.mbxbackup);
}
ESCvar.toggle = ESCvar.SM[1].ECrep;
ESCvar.SM[1].PDIrep = ESCvar.toggle;
ESCvar.SM[1].PDIrep = ESCvar.toggle & 0x1U;
ESC_SMwritepdi (1);
}
return 0;
@ -688,23 +712,78 @@ uint8_t ESC_checkSM23 (uint8_t state)
_ESCsm2 *SM;
ESC_read (ESCREG_SM2, (void *) &ESCvar.SM[2], sizeof (ESCvar.SM[2]));
SM = (_ESCsm2 *) & ESCvar.SM[2];
if ((etohs (SM->PSA) != ESC_SM2_sma) || (etohs (SM->Length) != ESCvar.ESC_SM2_sml)
|| (SM->Command != ESC_SM2_smc) || !(SM->ActESC & ESC_SM2_act))
/* Check SM settings */
if ((etohs (SM->PSA) != ESC_SM2_sma) ||
(SM->Command != ESC_SM2_smc))
{
ESCvar.SMtestresult = SMRESULT_ERRSM2;
/* fail state change */
return (ESCpreop | ESCerror);
}
/* Check run-time settings */
/* Check length */
else if (etohs (SM->Length) != ESCvar.ESC_SM2_sml)
{
ESCvar.SMtestresult = SMRESULT_ERRSM2;
/* fail state change */
return (ESCpreop | ESCerror);
}
/* SM disabled and (SM activated or length > 0) set by master */
else if (((ESC_SM2_act & ESCREG_SYNC_ACT_ACTIVATED) == 0) &&
((SM->ActESC & ESCREG_SYNC_ACT_ACTIVATED) || (ESCvar.ESC_SM2_sml > 0)))
{
ESCvar.SMtestresult = SMRESULT_ERRSM2;
/* fail state change */
return (ESCpreop | ESCerror);
}
/* SM enabled and (length > 0 but SM disabled) set by master */
else if (((ESC_SM2_act & ESCREG_SYNC_ACT_ACTIVATED) > 0) &&
((SM->ActESC & ESCREG_SYNC_ACT_ACTIVATED) == 0) &&
(ESCvar.ESC_SM2_sml > 0))
{
ESCvar.SMtestresult = SMRESULT_ERRSM2;
/* fail state change */
return (ESCpreop | ESCerror);
}
if ((ESC_SM2_sma + (etohs (SM->Length) * 3)) > ESC_SM3_sma)
{
ESCvar.SMtestresult = SMRESULT_ERRSM2;
/* SM2 overlaps SM3, fail state change */
return (ESCpreop | ESCerror);
}
ESC_read (ESCREG_SM3, (void *) &ESCvar.SM[3], sizeof (ESCvar.SM[3]));
SM = (_ESCsm2 *) & ESCvar.SM[3];
if ((etohs (SM->PSA) != ESC_SM3_sma) || (etohs (SM->Length) != ESCvar.ESC_SM3_sml)
|| (SM->Command != ESC_SM3_smc) || !(SM->ActESC & ESC_SM3_act))
/* Check SM settings */
if ((etohs (SM->PSA) != ESC_SM3_sma) ||
(SM->Command != ESC_SM3_smc))
{
ESCvar.SMtestresult = SMRESULT_ERRSM3;
/* fail state change */
return (ESCpreop | ESCerror);
}
/* Check run-time settings */
/* Check length */
else if (etohs (SM->Length) != ESCvar.ESC_SM3_sml)
{
ESCvar.SMtestresult = SMRESULT_ERRSM3;
/* fail state change */
return (ESCpreop | ESCerror);
}
/* SM disabled and (SM activated or length > 0) set by master */
else if (((ESC_SM3_act & ESCREG_SYNC_ACT_ACTIVATED) == 0) &&
((SM->ActESC & ESCREG_SYNC_ACT_ACTIVATED) || (ESCvar.ESC_SM3_sml > 0)))
{
ESCvar.SMtestresult = SMRESULT_ERRSM3;
/* fail state change */
return (ESCpreop | ESCerror);
}
/* SM enabled and (length > 0 but SM disabled) set by master */
else if (((ESC_SM3_act & ESCREG_SYNC_ACT_ACTIVATED) > 0) &&
((SM->ActESC & ESCREG_SYNC_ACT_ACTIVATED) == 0) &&
(ESCvar.ESC_SM3_sml > 0))
{
ESCvar.SMtestresult = SMRESULT_ERRSM3;
/* fail state change */
@ -727,7 +806,12 @@ uint8_t ESC_startinput (uint8_t state)
if (state != (ESCpreop | ESCerror))
{
ESC_SMenable (3);
/* If inputs > 0 , enable SM3 */
if (ESCvar.ESC_SM3_sml > 0)
{
ESC_SMenable (3);
}
/* Go to state input regardless of any inputs present */
CC_ATOMIC_SET(ESCvar.App.state, APPSTATE_INPUT);
}
else
@ -767,15 +851,22 @@ uint8_t ESC_startinput (uint8_t state)
{
if (ESCvar.esc_hw_interrupt_enable != NULL)
{
if(ESCvar.dcsync > 0)
uint32_t int_mask;
if (ESCvar.ESC_SM2_sml == 0)
{
ESCvar.esc_hw_interrupt_enable(ESCREG_ALEVENT_DC_SYNC0 |
ESCREG_ALEVENT_SM2);
int_mask = ESCREG_ALEVENT_SM3;
}
else
{
ESCvar.esc_hw_interrupt_enable(ESCREG_ALEVENT_SM2);
int_mask = ESCREG_ALEVENT_SM2;
}
if (ESCvar.dcsync > 0)
{
int_mask |= ESCREG_ALEVENT_DC_SYNC0;
}
ESCvar.esc_hw_interrupt_enable (int_mask);
}
}
}
@ -798,7 +889,8 @@ void ESC_stopinput (void)
(ESCvar.esc_hw_interrupt_disable != NULL))
{
ESCvar.esc_hw_interrupt_disable (ESCREG_ALEVENT_DC_SYNC0 |
ESCREG_ALEVENT_SM2);
ESCREG_ALEVENT_SM2 |
ESCREG_ALEVENT_SM3);
}
}
@ -812,8 +904,13 @@ void ESC_stopinput (void)
*/
uint8_t ESC_startoutput (uint8_t state)
{
ESC_SMenable (2);
/* If outputs > 0 , enable SM2 */
if (ESCvar.ESC_SM2_sml > 0)
{
ESC_SMenable (2);
}
/* Go to state output regardless of any outputs present */
CC_ATOMIC_OR(ESCvar.App.state, APPSTATE_OUTPUT);
return state;
@ -920,6 +1017,75 @@ void ESC_sm_act_event (void)
ESC_SMack (7);
}
}
static bool ESC_check_id_request (uint16_t ALcontrol, uint8_t * an)
{
if ((ALcontrol & ESCREG_AL_ID_REQUEST) != 0)
{
uint8_t state = ALcontrol & ESCREG_AL_ERRACKMASK;
if ((state != ESCboot) &&
((state < ESCsafeop) || (*an == ESCsafeop) || (*an == ESCop)))
{
uint16_t ALstatuscode;
ESC_read (ESCREG_ALERROR,
(void *)&ALstatuscode,
sizeof (ALstatuscode));
return (ALstatuscode == ALERR_NONE);
}
}
return false;
}
static uint8_t ESC_load_device_id (void)
{
uint16_t device_id;
if (ESCvar.get_device_id != NULL)
{
if (ESCvar.get_device_id (&device_id) != 0)
{
device_id = 0;
}
}
else
{
ESC_read (ESCREG_CONF_STATION_ALIAS,
(void *)&device_id,
sizeof (device_id));
}
if (device_id != 0)
{
/* Load the Device Identification Value to the AL Status Code register */
ESC_ALerror (device_id);
return ESCREG_AL_ID_REQUEST;
}
return 0;
}
#ifdef ESC_DEBUG
static char * ESC_state_to_string (uint8_t ESC_state)
{
switch (ESC_state)
{
case ESCinit: return "Init";
case ESCpreop: return "Pre-Operational";
case ESCboot: return "Bootstrap";
case ESCsafeop: return "Safe-Operational";
case ESCop: return "Operational";
case ESCerror: return "Error";
}
return "Unknown";
}
#endif
/** The state handler acting on ALControl Bit(0)
* events in the Al Event Request register 0x220.
*
@ -958,7 +1124,7 @@ void ESC_state (void)
}
/* Mask high bits ALcommand, low bits ALstatus */
as = (ac << 4) | (as & 0x0f);
as = (uint8_t)((ac << 4) | (as & 0x0f));
/* Call post state change hook case it have been configured */
if (ESCvar.pre_state_change_hook != NULL)
@ -1098,6 +1264,11 @@ void ESC_state (void)
an = ESCsafeop | ESCerror;
ESC_ALerror (ALERR_INVALIDSTATECHANGE);
ESC_stopoutput ();
/* If no outputs present, we need to flag error using SM3 */
if (ESCvar.ESC_SM2_sml == 0 && ESCvar.ESC_SM3_sml > 0)
{
ESC_SMdisable (3);
}
break;
}
case OP_TO_SAFEOP:
@ -1111,6 +1282,11 @@ void ESC_state (void)
if (an == ESCop)
{
ESC_stopoutput ();
/* If no outputs present, we need to flag error using SM3 */
if (ESCvar.ESC_SM2_sml == 0 && ESCvar.ESC_SM3_sml > 0)
{
ESC_SMdisable (3);
}
an = ESCsafeop;
}
if (as == ESCsafeop)
@ -1135,8 +1311,16 @@ void ESC_state (void)
ESC_ALerror (ALERR_NONE);
}
if (ESC_check_id_request (ESCvar.ALcontrol, &an))
{
an |= ESC_load_device_id ();
}
ESC_ALstatus (an);
DPRINT ("state %x\n", an);
#ifdef ESC_DEBUG
DPRINT ("state %s\n", ESC_state_to_string (an & 0xF));
#endif
}
/** Function copying the application configuration variable
* data to the stack local variable.
@ -1176,4 +1360,5 @@ void ESC_config (esc_cfg_t * cfg)
ESCvar.esc_hw_interrupt_disable = cfg->esc_hw_interrupt_disable;
ESCvar.esc_hw_eep_handler = cfg->esc_hw_eep_handler;
ESCvar.esc_check_dc_handler = cfg->esc_check_dc_handler;
ESCvar.get_device_id = cfg->get_device_id;
}

View File

@ -17,9 +17,12 @@
#include "options.h"
#define ESCREG_ADDRESS 0x0010
#define ESCREG_CONF_STATION_ALIAS 0x0012
#define ESCREG_DLSTATUS 0x0110
#define ESCREG_ALCONTROL 0x0120
#define ESCREG_ALCONTROL_ERROR_ACK 0x0010
#define ESCREG_ALSTATUS 0x0130
#define ESCREG_ALSTATUS_ERROR_IND 0x0010
#define ESCREG_ALERROR 0x0134
#define ESCREG_ALEVENTMASK 0x0204
#define ESCREG_ALEVENT 0x0220
@ -58,6 +61,7 @@
#define ESCREG_AL_STATEMASK 0x001f
#define ESCREG_AL_ALLBUTINITMASK 0x0e
#define ESCREG_AL_ERRACKMASK 0x0f
#define ESCREG_AL_ID_REQUEST 0x0020
#define SYNCTYPE_SUPPORT_FREERUN 0x01
#define SYNCTYPE_SUPPORT_SYNCHRON 0x02
@ -206,9 +210,9 @@
#define MBXstate_backup 0x05
#define MBXstate_again 0x06
#define COE_DEFAULTLENGTH 0x0a
#define COE_HEADERSIZE 0x0a
#define COE_SEGMENTHEADERSIZE 0x03
#define COE_DEFAULTLENGTH 0x0AU
#define COE_HEADERSIZE 0x0AU
#define COE_SEGMENTHEADERSIZE 0x03U
#define COE_SDOREQUEST 0x02
#define COE_SDORESPONSE 0x03
#define COE_SDOINFORMATION 0x08
@ -336,6 +340,7 @@ typedef struct esc_cfg
void (*esc_hw_interrupt_disable) (uint32_t mask);
void (*esc_hw_eep_handler) (void);
uint16_t (*esc_check_dc_handler) (void);
int (*get_device_id) (uint16_t * device_id);
} esc_cfg_t;
typedef struct
@ -460,8 +465,9 @@ typedef struct
void (*esc_hw_interrupt_disable) (uint32_t mask);
void (*esc_hw_eep_handler) (void);
uint16_t (*esc_check_dc_handler) (void);
int (*get_device_id) (uint16_t * device_id);
uint8_t MBXrun;
size_t activembxsize;
uint32_t activembxsize;
sm_cfg_t * activemb0;
sm_cfg_t * activemb1;
uint16_t ESC_SM2_sml;
@ -483,8 +489,8 @@ typedef struct
uint8_t segmented;
void *data;
uint16_t entries;
uint16_t frags;
uint16_t fragsleft;
uint32_t frags;
uint32_t fragsleft;
uint16_t index;
uint8_t subindex;
uint16_t flags;
@ -500,7 +506,7 @@ typedef struct
/* Volatile since it may be read from ISR */
volatile int watchdogcnt;
volatile uint32_t Time;
volatile uint16_t ALevent;
volatile uint32_t ALevent;
volatile int8_t synccounter;
volatile _App App;
uint8_t mbxdata[PREALLOC_BUFFER_SIZE];
@ -573,7 +579,7 @@ typedef struct CC_PACKED
CC_PACKED_END
CC_PACKED_BEGIN
typedef struct CC_PACKED
typedef struct CC_PACKED CC_ALIGNED(4)
{
_MBXh mbxheader;
_COEh coeheader;
@ -585,7 +591,7 @@ typedef struct CC_PACKED
CC_PACKED_END
CC_PACKED_BEGIN
typedef struct CC_PACKED
typedef struct CC_PACKED CC_ALIGNED(4)
{
_MBXh mbxheader;
_COEh coeheader;
@ -695,11 +701,11 @@ typedef struct
#define ESC_SM3_smc (SM3_smc)
#define ESC_SM3_act (SM3_act)
#define ESC_MBXHSIZE sizeof(_MBXh)
#define ESC_MBXHSIZE ((uint32_t)sizeof(_MBXh))
#define ESC_MBXDSIZE (ESC_MBXSIZE - ESC_MBXHSIZE)
#define ESC_FOEHSIZE sizeof(_FOEh)
#define ESC_FOEHSIZE (uint32_t)sizeof(_FOEh)
#define ESC_FOE_DATA_SIZE (ESC_MBXSIZE - (ESC_MBXHSIZE +ESC_FOEHSIZE))
#define ESC_EOEHSIZE sizeof(_EOEh)
#define ESC_EOEHSIZE ((uint32_t)sizeof(_EOEh))
#define ESC_EOE_DATA_SIZE (ESC_MBXSIZE - (ESC_MBXHSIZE +ESC_EOEHSIZE))
void ESC_config (esc_cfg_t * cfg);

View File

@ -18,7 +18,8 @@
#include "esc.h"
#include "esc_coe.h"
#define BITS2BYTES(b) ((b + 7) >> 3)
#define BITS2BYTES(b) ((b + 7U) >> 3)
#define BITSPOS2BYTESOFFSET(b) (b >> 3)
/* Fetch value from object dictionary */
#define OBJ_VALUE_FETCH(v, o) \
@ -47,7 +48,7 @@ typedef enum { UPLOAD, DOWNLOAD } load_t;
* @param[in] subindex = value on sub-index of object we want to locate
* @return local array index if we succeed, -1 if we didn't find the index.
*/
int16_t SDO_findsubindex (int16_t nidx, uint8_t subindex)
int16_t SDO_findsubindex (int32_t nidx, uint8_t subindex)
{
const _objd *objd;
int16_t n = 0;
@ -117,9 +118,10 @@ int32_t SDO_findobject (uint16_t index)
uint16_t sizeOfPDO (uint16_t index, int * nmappings, _SMmap * mappings,
int max_mappings)
{
uint16_t offset = 0, hobj;
uint32_t offset = 0;
uint16_t hobj;
uint8_t si, sic, c;
int16_t nidx;
int32_t nidx;
const _objd *objd;
const _objd *objd1c1x;
int mapIx = 0;
@ -158,7 +160,7 @@ uint16_t sizeOfPDO (uint16_t index, int * nmappings, _SMmap * mappings,
if (max_mappings > 0)
{
uint16_t index = value >> 16;
uint16_t index = (uint16_t)(value >> 16);
uint8_t subindex = (value >> 8) & 0xFF;
const _objd * mapping;
@ -169,7 +171,10 @@ uint16_t sizeOfPDO (uint16_t index, int * nmappings, _SMmap * mappings,
return 0;
}
DPRINT ("%04x:%02x @ %d\n", index, subindex, offset);
DPRINT ("%04"PRIx32":%02"PRIx32" @ %"PRIu32"\n",
index,
subindex,
offset);
if (index == 0 && subindex == 0)
{
@ -202,6 +207,15 @@ uint16_t sizeOfPDO (uint16_t index, int * nmappings, _SMmap * mappings,
}
mappings[mapIx].obj = mapping;
/* Save object list reference */
if(mapping != NULL)
{
mappings[mapIx].objectlistitem = &SDOobjects[nidx];
}
else
{
mappings[mapIx].objectlistitem = NULL;
}
mappings[mapIx++].offset = offset;
}
@ -220,7 +234,7 @@ uint16_t sizeOfPDO (uint16_t index, int * nmappings, _SMmap * mappings,
*nmappings = 0;
}
return BITS2BYTES (offset);
return BITS2BYTES (offset) & 0xFFFF;
}
/** Copy to mailbox.
@ -229,7 +243,7 @@ uint16_t sizeOfPDO (uint16_t index, int * nmappings, _SMmap * mappings,
* @param[in] dest = pointer to destination
* @param[in] size = Size to copy
*/
static void copy2mbx (void *source, void *dest, uint16_t size)
static void copy2mbx (void *source, void *dest, size_t size)
{
memcpy (dest, source, size);
}
@ -287,7 +301,8 @@ static void SDO_upload (void)
_COEsdo *coesdo, *coeres;
uint16_t index;
uint8_t subindex;
int16_t nidx, nsub;
int32_t nidx;
int16_t nsub;
uint8_t MBXout;
uint32_t size;
uint8_t dss;
@ -335,14 +350,14 @@ static void SDO_upload (void)
}
coeres->index = htoes (index);
coeres->subindex = subindex;
coeres->command = COE_COMMAND_UPLOADRESPONSE +
coeres->command = COE_COMMAND_UPLOADRESPONSE |
COE_SIZE_INDICATOR;
/* convert bits to bytes */
size = BITS2BYTES(size);
if (size <= 4)
{
/* expedited response i.e. length<=4 bytes */
coeres->command += COE_EXPEDITED_INDICATOR + dss;
coeres->command |= (COE_EXPEDITED_INDICATOR | dss);
void *dataptr = ((objd + nsub)->data) ?
(objd + nsub)->data : (void *)&((objd + nsub)->value);
abort = ESC_upload_pre_objecthandler (index, subindex,
@ -430,7 +445,7 @@ static void SDO_upload (void)
}
static uint32_t complete_access_get_variables(_COEsdo *coesdo, uint16_t *index,
uint8_t *subindex, int16_t *nidx,
uint8_t *subindex, int32_t *nidx,
int16_t *nsub)
{
*index = etohs (coesdo->index);
@ -458,11 +473,11 @@ static uint32_t complete_access_get_variables(_COEsdo *coesdo, uint16_t *index,
}
static uint32_t complete_access_subindex_loop(const _objd *objd,
int16_t nidx,
int32_t nidx,
int16_t nsub,
uint8_t *mbxdata,
load_t load_type,
uint16_t max_bytes)
uint32_t max_bytes)
{
/* Objects with dynamic entries cannot be accessed with Complete Access */
if ((objd->datatype == DTYPE_VISIBLE_STRING) ||
@ -474,6 +489,12 @@ static uint32_t complete_access_subindex_loop(const _objd *objd,
uint32_t size = 0;
/* Clear padded mbxdata byte [1] on upload */
if ((load_type == UPLOAD) && (mbxdata != NULL))
{
mbxdata[1] = 0;
}
while (nsub <= SDOobjects[nidx].maxsub)
{
uint16_t bitlen = (objd + nsub)->bitlength;
@ -488,7 +509,7 @@ static uint32_t complete_access_subindex_loop(const _objd *objd,
if (bitoffset != 0)
{
/* move on to next byte boundary */
size += (8 - bitoffset);
size += (8U - bitoffset);
}
if (mbxdata != NULL)
{
@ -517,24 +538,29 @@ static uint32_t complete_access_subindex_loop(const _objd *objd,
else if ((load_type == UPLOAD) && (mbxdata != NULL))
{
/* copy a bit data type into correct position */
uint8_t bitmask = (1 << bitlen) - 1;
uint32_t bitmask = (1U << bitlen) - 1U;
uint32_t tempmask;
if (READ_ACCESS(access, state))
{
if (bitoffset == 0)
{
mbxdata[BITS2BYTES(size)] = 0;
mbxdata[BITSPOS2BYTESOFFSET(size)] = 0;
}
mbxdata[BITS2BYTES(size)] |=
(*(uint8_t *)ul_source & bitmask) << bitoffset;
tempmask = (*(uint8_t *)ul_source & bitmask) << bitoffset;
mbxdata[BITSPOS2BYTESOFFSET(size)] |= (uint8_t)tempmask;
}
else
{
mbxdata[BITS2BYTES(size)] &= ~(bitmask << bitoffset);
tempmask = ~(bitmask << bitoffset);
mbxdata[BITSPOS2BYTESOFFSET(size)] &= (uint8_t)tempmask;
}
}
/* Subindex 0 is padded to 16 bit */
size += (nsub == 0) ? 16 : bitlen;
/* Subindex 0 is padded to 16 bit if not object type VARIABLE.
* For VARIABLE use true bitsize.
*/
size +=
((nsub == 0) && (SDOobjects[nidx].objtype != OTYPE_VAR)) ? 16 : bitlen;
nsub++;
if ((max_bytes > 0) && (BITS2BYTES(size) >= max_bytes))
@ -570,7 +596,8 @@ static void SDO_upload_complete_access (void)
_COEsdo *coesdo = (_COEsdo *) &MBX[0];
uint16_t index;
uint8_t subindex;
int16_t nidx, nsub;
int32_t nidx;
int16_t nsub;
uint32_t abortcode = complete_access_get_variables
(coesdo, &index, &subindex, &nidx, &nsub);
if (abortcode != 0)
@ -595,7 +622,7 @@ static void SDO_upload_complete_access (void)
uint32_t size = complete_access_subindex_loop(objd, nidx, nsub, NULL, UPLOAD, 0);
/* expedited bits used calculation */
uint8_t dss = (size > 24) ? 0 : (4 * (3 - ((size - 1) >> 3)));
uint8_t dss = (size > 24) ? 0 : (uint8_t)(4U * (3U - ((size - 1U) >> 3)));
/* convert bits to bytes */
size = BITS2BYTES(size);
@ -693,7 +720,7 @@ static void SDO_uploadsegment (void)
coeres = (_COEsdo *) &MBX[MBXout * ESC_MBXSIZE];
offset = ESCvar.fragsleft;
size = ESCvar.frags - ESCvar.fragsleft;
uint8_t command = COE_COMMAND_UPLOADSEGMENT +
uint8_t command = COE_COMMAND_UPLOADSEGMENT |
(coesdo->command & COE_TOGGLEBIT); /* copy toggle bit */
init_coesdo(coeres, COE_SDORESPONSE, command,
coesdo->index, coesdo->subindex);
@ -712,14 +739,14 @@ static void SDO_uploadsegment (void)
ESCvar.segmented = 0;
ESCvar.frags = 0;
ESCvar.fragsleft = 0;
coeres->command += COE_COMMAND_LASTSEGMENTBIT;
coeres->command |= COE_COMMAND_LASTSEGMENTBIT;
if (size >= 7)
{
coeres->mbxheader.length = htoes (COE_SEGMENTHEADERSIZE + size);
}
else
{
coeres->command += (7 - size) << 1;
coeres->command |= (uint8_t)((7U - size) << 1);
coeres->mbxheader.length = htoes (COE_DEFAULTLENGTH);
}
}
@ -752,9 +779,10 @@ static void SDO_download (void)
_COEsdo *coesdo, *coeres;
uint16_t index;
uint8_t subindex;
int16_t nidx, nsub;
int32_t nidx;
int16_t nsub;
uint8_t MBXout;
uint16_t size, actsize;
uint32_t size, actsize;
const _objd *objd;
uint32_t *mbxdata;
uint32_t abort;
@ -776,7 +804,7 @@ static void SDO_download (void)
/* expedited? */
if (coesdo->command & COE_EXPEDITED_INDICATOR)
{
size = 4 - ((coesdo->command & 0x0c) >> 2);
size = 4U - ((coesdo->command & 0x0CU) >> 2);
mbxdata = &(coesdo->size);
}
else
@ -865,13 +893,14 @@ static void SDO_download (void)
}
else
{
if (access == ATYPE_RWpre)
if (access == ATYPE_RO)
{
SDO_abort (0, index, subindex, ABORT_NOTINTHISSTATE);
SDO_abort (0, index, subindex, ABORT_READONLY);
}
else
{
SDO_abort (0, index, subindex, ABORT_READONLY);
SDO_abort (0, index, subindex, ABORT_NOTINTHISSTATE);
}
}
}
@ -897,7 +926,8 @@ static void SDO_download_complete_access (void)
_COEsdo *coesdo = (_COEsdo *) &MBX[0];
uint16_t index;
uint8_t subindex;
int16_t nidx, nsub;
int32_t nidx;
int16_t nsub;
uint32_t abortcode = complete_access_get_variables
(coesdo, &index, &subindex, &nidx, &nsub);
if (abortcode != 0)
@ -906,13 +936,13 @@ static void SDO_download_complete_access (void)
return;
}
uint16_t bytes;
uint32_t bytes;
uint32_t *mbxdata = &(coesdo->size);
if (coesdo->command & COE_EXPEDITED_INDICATOR)
{
/* expedited download */
bytes = 4 - ((coesdo->command & 0x0c) >> 2);
bytes = 4U - ((coesdo->command & 0x0CU) >> 2);
}
else
{
@ -925,7 +955,8 @@ static void SDO_download_complete_access (void)
/* loop through the subindexes to get the total size */
uint32_t size = complete_access_subindex_loop(objd, nidx, nsub, NULL, DOWNLOAD, 0);
if (BITS2BYTES(size) > 0xffff)
size = BITS2BYTES(size);
if (size > 0xffff)
{
/* 'size' is in this case actually an abort code */
set_state_idle (0, index, subindex, size);
@ -937,7 +968,7 @@ static void SDO_download_complete_access (void)
* But EtherCAT Conformance Test Tool doesn't follow this rule for some test
* cases, which is the reason to here only check for 'less than or equal'.
*/
else if (bytes <= BITS2BYTES(size))
else if (bytes <= size)
{
abortcode = ESC_download_pre_objecthandler(index, subindex, mbxdata,
size, objd->flags | COMPLETE_ACCESS_FLAG);
@ -947,15 +978,41 @@ static void SDO_download_complete_access (void)
return;
}
/* copy download data to subindexes */
complete_access_subindex_loop(objd, nidx, nsub, (uint8_t *)mbxdata, DOWNLOAD, bytes);
abortcode = ESC_download_post_objecthandler(index, subindex,
objd->flags | COMPLETE_ACCESS_FLAG);
if (abortcode != 0)
if ((bytes + COE_HEADERSIZE) > ESC_MBXDSIZE)
{
set_state_idle (0, index, subindex, abortcode);
return;
/* check that download data fits in the preallocated buffer */
if ((bytes + PREALLOC_FACTOR * COE_HEADERSIZE) > PREALLOC_BUFFER_SIZE)
{
set_state_idle(0, index, subindex, ABORT_CA_NOT_SUPPORTED);
return;
}
/* set total size in bytes */
ESCvar.frags = bytes;
/* limit to mailbox size */
size = ESC_MBXDSIZE - COE_HEADERSIZE;
/* number of bytes done */
ESCvar.fragsleft = size;
ESCvar.segmented = MBXSED;
ESCvar.data = ESCvar.mbxdata + size;
ESCvar.index = index;
ESCvar.subindex = subindex;
ESCvar.flags = COMPLETE_ACCESS_FLAG;
/* Store the data */
copy2mbx (mbxdata, ESCvar.mbxdata, size);
}
else
{
ESCvar.segmented = 0;
/* copy download data to subindexes */
complete_access_subindex_loop(objd, nidx, nsub, (uint8_t *)mbxdata, DOWNLOAD, bytes);
abortcode = ESC_download_post_objecthandler(index, subindex,
objd->flags | COMPLETE_ACCESS_FLAG);
if (abortcode != 0)
{
set_state_idle (0, index, subindex, abortcode);
return;
}
}
}
else
@ -986,23 +1043,55 @@ static void SDO_downloadsegment (void)
if (MBXout)
{
_COEsdo *coeres = (_COEsdo *) &MBX[MBXout * ESC_MBXSIZE];
uint32_t size = coesdo->mbxheader.length - 3;
uint32_t size = coesdo->mbxheader.length - 3U;
if (size == 7)
{
size = 7 - ((coesdo->command >> 1) & 7);
}
uint8_t command = COE_COMMAND_DOWNLOADSEGRESP +
(coesdo->command & COE_TOGGLEBIT); /* copy toggle bit */
uint8_t command = COE_COMMAND_DOWNLOADSEGRESP;
uint8_t command2 = (coesdo->command & COE_TOGGLEBIT); /* copy toggle bit */
command |= command2;
init_coesdo(coeres, COE_SDORESPONSE, command, 0, 0);
uint32_t *mbxdata = (uint32_t *)&(coesdo->index); /* data pointer */
copy2mbx (mbxdata, (uint8_t *)ESCvar.data, size);
void *mbxdata = &(coesdo->index); /* data pointer */
copy2mbx (mbxdata, ESCvar.data, size);
if (coesdo->command & COE_COMMAND_LASTSEGMENTBIT)
{
if(ESCvar.flags == COMPLETE_ACCESS_FLAG)
{
int32_t nidx;
int16_t nsub;
if(ESCvar.frags > ESCvar.fragsleft + size)
{
set_state_idle (0, ESCvar.index, ESCvar.subindex, ABORT_TYPEMISMATCH);
return;
}
nidx = SDO_findobject(ESCvar.index);
nsub = SDO_findsubindex (nidx, ESCvar.subindex);
if ((nidx < 0) || (nsub < 0))
{
set_state_idle (0, ESCvar.index, ESCvar.subindex, ABORT_NOOBJECT);
return;
}
/* copy download data to subindexes */
const _objd *objd = SDOobjects[nidx].objdesc;
complete_access_subindex_loop(objd,
nidx,
nsub,
(uint8_t *)ESCvar.mbxdata,
DOWNLOAD,
ESCvar.frags);
}
/* last segment */
ESCvar.segmented = 0;
ESCvar.frags = 0;
ESCvar.fragsleft = 0;
/* external object write handler */
uint32_t abort = ESC_download_post_objecthandler
(ESCvar.index, ESCvar.subindex, ESCvar.flags);
@ -1016,6 +1105,8 @@ static void SDO_downloadsegment (void)
{
/* more segmented transfer needed: increase offset */
ESCvar.data += size;
/* number of bytes done */
ESCvar.fragsleft += size;
}
MBXcontrol[MBXout].state = MBXstate_outreq;
@ -1036,7 +1127,7 @@ static void SDO_infoerror (uint32_t abortcode)
if (MBXout)
{
coeres = (_COEobjdesc *) &MBX[MBXout * ESC_MBXSIZE];
coeres->mbxheader.length = htoes ((uint16_t) COE_HEADERSIZE);
coeres->mbxheader.length = htoes (COE_HEADERSIZE);
coeres->mbxheader.mbxtype = MBXCOE;
coeres->coeheader.numberservice =
htoes ((0 & 0x01f) | (COE_SDOINFORMATION << 12));
@ -1053,14 +1144,14 @@ static void SDO_infoerror (uint32_t abortcode)
}
}
#define ODLISTSIZE ((ESC_MBX1_sml - ESC_MBXHSIZE - sizeof(_COEh) - sizeof(_INFOh) - 2) & 0xfffe)
#define ODLISTSIZE ((uint32_t)(ESC_MBX1_sml - ESC_MBXHSIZE - sizeof(_COEh) - sizeof(_INFOh) - 2U) & 0xfffe)
/** Function for handling incoming requested SDO Get OD List, validating the
* request and sending an response. On error an SDO Info Error will be sent.
*/
static void SDO_getodlist (void)
{
uint16_t frags;
uint32_t frags;
uint8_t MBXout = 0;
uint16_t entries = 0;
uint16_t i, n;
@ -1072,7 +1163,7 @@ static void SDO_getodlist (void)
entries++;
}
ESCvar.entries = entries;
frags = ((entries << 1) + ODLISTSIZE - 1);
frags = ((uint32_t)(entries << 1) + ODLISTSIZE - 1U);
frags /= ODLISTSIZE;
coer = (_COEobjdesc *) &MBX[0];
/* check for unsupported opcodes */
@ -1094,10 +1185,10 @@ static void SDO_getodlist (void)
/* number of objects request */
if (etohs (coer->index) == 0x00)
{
coel->index = htoes ((uint16_t) 0x00);
coel->index = htoes (0x00);
coel->infoheader.incomplete = 0;
coel->infoheader.reserved = 0x00;
coel->infoheader.fragmentsleft = htoes ((uint16_t) 0);
coel->infoheader.fragmentsleft = htoes (0);
MBXcontrol[0].state = MBXstate_idle;
ESCvar.xoe = 0;
ESCvar.frags = frags;
@ -1134,7 +1225,7 @@ static void SDO_getodlist (void)
ESCvar.frags = frags;
ESCvar.fragsleft = frags - 1;
coel->infoheader.fragmentsleft = htoes (ESCvar.fragsleft);
coel->index = htoes ((uint16_t) 0x01);
coel->index = htoes (0x01);
p = &(coel->datatype);
for (i = 0; i < n; i++)
@ -1164,13 +1255,13 @@ static void SDO_getodlistcont (void)
coel = (_COEobjdesc *) &MBX[MBXout * ESC_MBXSIZE];
coel->mbxheader.mbxtype = MBXCOE;
coel->coeheader.numberservice =
htoes ((0 & 0x01f) | (COE_SDOINFORMATION << 12));
htoes (COE_SDOINFORMATION << 12);
coel->infoheader.opcode = COE_GETODLISTRESPONSE;
s = (ESCvar.frags - ESCvar.fragsleft) * (ODLISTSIZE >> 1);
s = (uint16_t)((ESCvar.frags - ESCvar.fragsleft) * (ODLISTSIZE >> 1));
if (ESCvar.fragsleft > 1)
{
coel->infoheader.incomplete = 1;
n = s + (ODLISTSIZE >> 1);
n = (uint16_t)(s + (ODLISTSIZE >> 1));
}
else
{
@ -1181,7 +1272,7 @@ static void SDO_getodlistcont (void)
}
coel->infoheader.reserved = 0x00;
ESCvar.fragsleft--;
coel->infoheader.fragmentsleft = htoes (ESCvar.fragsleft);
coel->infoheader.fragmentsleft = htoes ((uint16_t)ESCvar.fragsleft);
/* pointer 2 bytes back to exclude index */
p = &(coel->index);
for (i = s; i < n; i++)
@ -1218,7 +1309,7 @@ static void SDO_getod (void)
coel = (_COEobjdesc *) &MBX[MBXout * ESC_MBXSIZE];
coel->mbxheader.mbxtype = MBXCOE;
coel->coeheader.numberservice =
htoes ((0 & 0x01f) | (COE_SDOINFORMATION << 12));
htoes (COE_SDOINFORMATION << 12);
coel->infoheader.opcode = COE_GETODRESPONSE;
coel->infoheader.incomplete = 0;
coel->infoheader.reserved = 0x00;
@ -1236,14 +1327,14 @@ static void SDO_getod (void)
int32_t nsub = SDO_findsubindex (nidx, 0);
const _objd *objd = SDOobjects[nidx].objdesc;
coel->datatype = htoes ((objd + nsub)->datatype);
coel->maxsub = SDOobjects[nidx].objdesc->value;
coel->maxsub = (uint8_t)SDOobjects[nidx].objdesc->value;
}
else
{
coel->datatype = htoes (0);
coel->maxsub = SDOobjects[nidx].objdesc->value;
coel->maxsub = (uint8_t)SDOobjects[nidx].objdesc->value;
}
coel->objectcode = SDOobjects[nidx].objtype;
coel->objectcode = (uint8_t)SDOobjects[nidx].objtype;
s = (uint8_t *) SDOobjects[nidx].name;
d = (uint8_t *) &(coel->name);
while (*s && (n < (ESC_MBXDSIZE - 0x0c)))
@ -1254,7 +1345,7 @@ static void SDO_getod (void)
d++;
}
*d = *s;
coel->mbxheader.length = htoes ((uint16_t) 0x0c + n);
coel->mbxheader.length = htoes (0x0C + n);
MBXcontrol[MBXout].state = MBXstate_outreq;
MBXcontrol[0].state = MBXstate_idle;
ESCvar.xoe = 0;
@ -1274,7 +1365,8 @@ static void SDO_geted (void)
{
uint8_t MBXout;
uint16_t index;
int32_t nidx, nsub;
int32_t nidx;
int16_t nsub;
uint8_t subindex;
uint8_t *d;
const uint8_t *s;
@ -1301,7 +1393,7 @@ static void SDO_geted (void)
coel->infoheader.opcode = COE_ENTRYDESCRIPTIONRESPONSE;
coel->infoheader.incomplete = 0;
coel->infoheader.reserved = 0x00;
coel->infoheader.fragmentsleft = htoes ((uint16_t) 0);
coel->infoheader.fragmentsleft = htoes (0);
coel->index = htoes (index);
coel->subindex = subindex;
coel->valueinfo = COE_VALUEINFO_ACCESS +
@ -1319,7 +1411,7 @@ static void SDO_geted (void)
d++;
}
*d = *s;
coel->mbxheader.length = htoes ((uint16_t) 0x10 + n);
coel->mbxheader.length = htoes (0x10 + n);
MBXcontrol[MBXout].state = MBXstate_outreq;
MBXcontrol[0].state = MBXstate_idle;
ESCvar.xoe = 0;
@ -1345,7 +1437,7 @@ void ESC_coeprocess (void)
_MBXh *mbh;
_COEsdo *coesdo;
_COEobjdesc *coeobjdesc;
uint8_t service;
uint16_t service;
if (ESCvar.MBXrun == 0)
{
return;
@ -1472,10 +1564,10 @@ void ESC_coeprocess (void)
* @param[in] length = number of bits to get
* @return bitslice value
*/
static uint64_t COE_bitsliceGet (uint64_t * bitmap, int offset, int length)
static uint64_t COE_bitsliceGet (uint64_t * bitmap, unsigned int offset, unsigned int length)
{
const int word_offset = offset / 64;
const int bit_offset = offset % 64;
const unsigned int word_offset = offset / 64;
const unsigned int bit_offset = offset % 64;
const uint64_t mask = (length == 64) ? UINT64_MAX : (1ULL << length) - 1;
uint64_t w0;
uint64_t w1 = 0;
@ -1505,11 +1597,11 @@ static uint64_t COE_bitsliceGet (uint64_t * bitmap, int offset, int length)
* @param[in] length = number of bits to set
* @param[in] value = value to set
*/
static void COE_bitsliceSet (uint64_t * bitmap, int offset, int length,
static void COE_bitsliceSet (uint64_t * bitmap, unsigned int offset, unsigned int length,
uint64_t value)
{
const int word_offset = offset / 64;
const int bit_offset = offset % 64;
const unsigned int word_offset = offset / 64;
const unsigned int bit_offset = offset % 64;
const uint64_t mask = (length == 64) ? UINT64_MAX : (1ULL << length) - 1;
const uint64_t mask0 = mask << bit_offset;
uint64_t v0 = value << bit_offset;
@ -1670,7 +1762,10 @@ void COE_initDefaultValues (void)
if (objd[i].data != NULL)
{
COE_setValue (&objd[i], objd[i].value);
DPRINT ("%04x:%02x = %x\n", SDOobjects[n].index, objd[i].subindex, objd[i].value);
DPRINT ("%04"PRIx32":%02"PRIx32" = %"PRIx32"\n",
SDOobjects[n].index,
objd[i].subindex,
objd[i].value);
}
} while (objd[i++].subindex < maxsub);
}
@ -1702,14 +1797,14 @@ void COE_pdoPack (uint8_t * buffer, int nmappings, _SMmap * mappings)
for (ix = 0; ix < nmappings; ix++)
{
const _objd * obj = mappings[ix].obj;
uint16_t offset = mappings[ix].offset;
uint32_t offset = mappings[ix].offset;
if (obj != NULL)
{
if (obj->bitlength > 64)
{
memcpy (
&buffer[BITS2BYTES (offset)],
&buffer[BITSPOS2BYTESOFFSET (offset)],
obj->data,
BITS2BYTES (obj->bitlength)
);
@ -1749,7 +1844,7 @@ void COE_pdoUnpack (uint8_t * buffer, int nmappings, _SMmap * mappings)
for (ix = 0; ix < nmappings; ix++)
{
const _objd * obj = mappings[ix].obj;
uint16_t offset = mappings[ix].offset;
uint32_t offset = mappings[ix].offset;
if (obj != NULL)
{
@ -1757,7 +1852,7 @@ void COE_pdoUnpack (uint8_t * buffer, int nmappings, _SMmap * mappings)
{
memcpy (
obj->data,
&buffer[BITS2BYTES (offset)],
&buffer[BITSPOS2BYTESOFFSET (offset)],
BITS2BYTES (obj->bitlength)
);
}
@ -1784,7 +1879,7 @@ void COE_pdoUnpack (uint8_t * buffer, int nmappings, _SMmap * mappings)
*/
uint8_t COE_maxSub (uint16_t index)
{
int nidx;
int32_t nidx;
uint8_t maxsub;
nidx = SDO_findobject (index);

View File

@ -13,8 +13,8 @@
#include <cc.h>
CC_PACKED_BEGIN
typedef struct CC_PACKED
typedef struct
{
uint16_t subindex;
uint16_t datatype;
@ -24,10 +24,9 @@ typedef struct CC_PACKED
uint32_t value;
void *data;
} _objd;
CC_PACKED_END
CC_PACKED_BEGIN
typedef struct CC_PACKED
typedef struct
{
uint16_t index;
uint16_t objtype;
@ -36,12 +35,13 @@ typedef struct CC_PACKED
const char *name;
const _objd *objdesc;
} _objectlist;
CC_PACKED_END
typedef struct
{
const _objd * obj;
uint16_t offset;
const _objectlist * objectlistitem;
uint32_t offset;
} _SMmap;
#define OBJH_READ 0
@ -96,11 +96,15 @@ typedef struct
#define ATYPE_Wop 0x20
#define ATYPE_RXPDO 0x40
#define ATYPE_TXPDO 0x80
#define ATYPE_BACKUP 0x100
#define ATYPE_SETTING 0x200
#define ATYPE_RO (ATYPE_Rpre | ATYPE_Rsafe | ATYPE_Rop)
#define ATYPE_WO (ATYPE_Wpre | ATYPE_Wsafe | ATYPE_Wop)
#define ATYPE_RW (ATYPE_RO | ATYPE_WO)
#define ATYPE_RWpre (ATYPE_Wpre | ATYPE_RO)
#define ATYPE_RWop (ATYPE_Wop | ATYPE_RO)
#define ATYPE_RWpre_safe (ATYPE_Wpre | ATYPE_Wsafe | ATYPE_RO)
#define TX_PDO_OBJIDX 0x1c13
#define RX_PDO_OBJIDX 0x1c12
@ -108,7 +112,7 @@ typedef struct
#define COMPLETE_ACCESS_FLAG (1 << 15)
void ESC_coeprocess (void);
int16_t SDO_findsubindex (int16_t nidx, uint8_t subindex);
int16_t SDO_findsubindex (int32_t nidx, uint8_t subindex);
int32_t SDO_findobject (uint16_t index);
uint16_t sizeOfPDO (uint16_t index, int * nmappings, _SMmap * sm, int max_mappings);
void COE_initDefaultValues (void);

View File

@ -15,6 +15,8 @@
#include <string.h>
static uint8_t eep_buf[8];
static uint16_t eep_read_size = 8U;
static void (*eep_reload_ptr)(eep_stat_t *stat) = NULL;
/** EPP periodic task of ESC side EEPROM emulation.
*
@ -51,19 +53,53 @@ void EEP_process (void)
break;
case EEP_CMD_READ:
case EEP_CMD_RELOAD:
/* handle read request */
if (EEP_read (stat.addr * sizeof(uint16_t), eep_buf, EEP_READ_SIZE) != 0) {
if (EEP_read (stat.addr * 2U /* sizeof(uint16_t) */, eep_buf, eep_read_size) != 0) {
stat.contstat.bits.ackErr = 1;
} else {
ESC_write (ESCREG_EEDATA, eep_buf, EEP_READ_SIZE);
}
else {
ESC_write(ESCREG_EEDATA, eep_buf, eep_read_size);
}
break;
case EEP_CMD_RELOAD:
/* user defined reload if set */
if (eep_reload_ptr != NULL) {
/* Reload function is responsible to update
* control status register bits.
*/
(*eep_reload_ptr)(&stat);
}
else {
if (eep_read_size == 8U) {
/* handle reload request */
if (EEP_read(stat.addr * 2U /* sizeof(uint16_t) */, eep_buf, eep_read_size) != 0) {
stat.contstat.bits.ackErr = 1;
}
else {
ESC_write(ESCREG_EEDATA, eep_buf, eep_read_size);
}
}
else {
/* Default handler of reload request for 4 Byte read, load config alias.
* To support other ESC behavior, implement user defined reload.
*/
if (EEP_read(EEP_CONFIG_ALIAS_WORD_OFFSET * 2U /* sizeof(uint16_t) */,
eep_buf,
2U /* 2 Bytes config alias*/) != 0) {
stat.contstat.bits.ackErr = 1;
}
else {
ESC_write(ESCREG_EEDATA, eep_buf, 2U /* 2 Bytes config alias*/);
}
}
}
break;
case EEP_CMD_WRITE:
/* handle write request */
ESC_read (ESCREG_EEDATA, eep_buf, EEP_WRITE_SIZE);
if (EEP_write (stat.addr * sizeof(uint16_t), eep_buf, EEP_WRITE_SIZE) != 0) {
if (EEP_write (stat.addr * 2U /* sizeof(uint16_t) */, eep_buf, EEP_WRITE_SIZE) != 0) {
stat.contstat.bits.ackErr = 1;
}
break;
@ -78,3 +114,24 @@ void EEP_process (void)
}
}
/** EPP Set read size, 4 Byte or 8 Byte depending on ESC.
* Default 8 Byte.
*/
void EEP_set_read_size (uint16_t read_size)
{
if ((read_size == 8U) || (read_size == 4U)) {
eep_read_size = read_size;
}
}
/** EPP Set reload function pointer.
* Function shall update current stat accordingly.
* Eg. on CRC error reload function shall set
* stat.contstat.bits.csumErr = 1
* stat.contstat.bits.ackErr = 1
*
*/
void EEP_set_reload_function_pointer(void (*reload_ptr)(eep_stat_t* stat))
{
eep_reload_ptr = reload_ptr;
}

View File

@ -15,14 +15,16 @@
#include "esc.h"
/* EEPROM commands */
#define EEP_CMD_IDLE 0x0
#define EEP_CMD_READ 0x1
#define EEP_CMD_WRITE 0x2
#define EEP_CMD_RELOAD 0x3
#define EEP_CMD_IDLE 0x0
#define EEP_CMD_READ 0x1
#define EEP_CMD_WRITE 0x2
#define EEP_CMD_RELOAD 0x4
/* read/write size */
#define EEP_READ_SIZE 8
#define EEP_WRITE_SIZE 2
/* write size */
#define EEP_WRITE_SIZE 2
/* EEPROm word offset */
#define EEP_CONFIG_ALIAS_WORD_OFFSET 4
/* CONSTAT register content */
typedef struct CC_PACKED
@ -69,6 +71,80 @@ typedef union eep_config
/* periodic task */
void EEP_process (void);
/**
* Application Notes: EEPROM emulation
*
* NOTE: Special handling needed when 4 Byte read is supported.
*
* Ref. ET1100 Datasheet sec2_registers_3i0, chapter 2.45.1,
* "EEPROM emulation with 32 bit EEPROM data register (0x0502[6]=0)".
*
* For a Reload command, fill the EEPROM Data register with the
* values shown in the chapter 2.45.1 before acknowledging
* the command. These values are automatically transferred to the
* designated registers after the Reload command is acknowledged.
*
* NOTE: When 4 Byte read is supported, EEP_process will only load
* config alias on reload.
*
* NOTE: EEP_process support implementing a custom reload function
* for both 4 Byte and 8 Byte read support.
*
* NOTE: Code snippet for custom reload function when 4 Byte read is supported.
*
* void reload_ptr(eep_stat_t *stat)
* {
* eep_config_t ee_cfg;
*
* // Read configuration area
* EEP_read(0, &ee_cfg, sizeof(ee_cfg);
*
* // Check CRC
* if(is_crc_ok(&ee_cfg) == true)
* {
* // Write config alias to EEPROM data registers.
* // Will be loaded to 0x12:13 on command ack.
* ESC_write(ESCREG_EEDATA,
* &ee_cfg.configured_station_alias,
* sizeof(configured_station_alias));
* }
* else
* {
* // Indicate CRC error
* stat->contstat.bits.csumErr = 1;
* stat->contstat.bits.ackErr = 1;
* }
* }
* NOTE: Code snippet for custom reload function when 8 Byte read is supported.
*
* void reload_ptr(eep_stat_t *stat)
* {
* eep_config_t ee_cfg;
*
* // Read configuration area
* EEP_read(0, &ee_cfg, sizeof(ee_cfg);
*
* // Check CRC
* if(is_crc_ok(&ee_cfg) == true)
* {
* // Load EEPROM data at requested EEPROM address
* EEP_read (stat->addr * sizeof(uint16_t), eep_buf, 8U);
* // Write loaded data to EEPROM data registers
* ESC_write(ESCREG_EEDATA, eep_buf, 8U);
* }
* else
* {
* // Indicate CRC error
* stat->contstat.bits.csumErr = 1;
* stat->contstat.bits.ackErr = 1;
* }
* }
*/
/* Set eep internal variables */
void EEP_set_read_size (uint16_t read_size);
void EEP_set_reload_function_pointer (void (*reload_ptr)(eep_stat_t *stat));
/* From hardware file */
void EEP_init (void);
int8_t EEP_read (uint32_t addr, uint8_t *data, uint16_t size);

View File

@ -20,12 +20,12 @@
#define EOE_HTONL(x) (x)
#define EOE_NTOHL(x) (x)
#else
#define EOE_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8))
#define EOE_HTONS(x) ((((x) & 0x00ffU) << 8) | (((x) & 0xff00U) >> 8))
#define EOE_NTOHS(x) EOE_HTONS(x)
#define EOE_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
#define EOE_HTONL(x) ((((x) & 0x000000ffU) << 24) | \
(((x) & 0x0000ff00U) << 8) | \
(((x) & 0x00ff0000U) >> 8) | \
(((x) & 0xff000000U) >> 24))
#define EOE_NTOHL(x) EOE_HTONL(x)
#endif /* #if defined(EC_BIG_ENDIAN) */
@ -47,37 +47,37 @@
/** Header frame info 1 */
#define EOE_HDR_FRAME_TYPE_OFFSET 0
#define EOE_HDR_FRAME_TYPE (0xF << 0)
#define EOE_HDR_FRAME_TYPE_SET(x) (((x) & 0xF) << 0)
#define EOE_HDR_FRAME_TYPE_SET(x) ((uint16_t)(((x) & 0xF) << 0))
#define EOE_HDR_FRAME_TYPE_GET(x) (((x) >> 0) & 0xF)
#define EOE_HDR_FRAME_PORT_OFFSET 4
#define EOE_HDR_FRAME_PORT (0xF << 4)
#define EOE_HDR_FRAME_PORT_SET(x) (((x) & 0xF) << 4)
#define EOE_HDR_FRAME_PORT_SET(x) ((uint16_t)(((x) & 0xF) << 4))
#define EOE_HDR_FRAME_PORT_GET(x) (((x) >> 4) & 0xF)
#define EOE_HDR_LAST_FRAGMENT_OFFSET 8
#define EOE_HDR_LAST_FRAGMENT (0x1 << 8)
#define EOE_HDR_LAST_FRAGMENT_SET(x) (((x) & 0x1) << 8)
#define EOE_HDR_LAST_FRAGMENT_SET(x) ((uint16_t)(((x) & 0x1) << 8))
#define EOE_HDR_LAST_FRAGMENT_GET(x) (((x) >> 8) & 0x1)
#define EOE_HDR_TIME_APPEND_OFFSET 9
#define EOE_HDR_TIME_APPEND (0x1 << 9)
#define EOE_HDR_TIME_APPEND_SET(x) (((x) & 0x1) << 9)
#define EOE_HDR_TIME_APPEND_SET(x) ((uint16_t)(((x) & 0x1) << 9))
#define EOE_HDR_TIME_APPEND_GET(x) (((x) >> 9) & 0x1)
#define EOE_HDR_TIME_REQUEST_OFFSET 10
#define EOE_HDR_TIME_REQUEST (0x1 << 10)
#define EOE_HDR_TIME_REQUEST_SET(x) (((x) & 0x1) << 10)
#define EOE_HDR_TIME_REQUEST_SET(x) ((uint16_t)(((x) & 0x1) << 10))
#define EOE_HDR_TIME_REQUEST_GET(x) (((x) >> 10) & 0x1)
/** Header frame info 2 */
#define EOE_HDR_FRAG_NO_OFFSET 0
#define EOE_HDR_FRAG_NO (0x3F << 0)
#define EOE_HDR_FRAG_NO_SET(x) (((x) & 0x3F) << 0)
#define EOE_HDR_FRAG_NO_SET(x) ((uint16_t)(((x) & 0x3F) << 0))
#define EOE_HDR_FRAG_NO_GET(x) (((x) >> 0) & 0x3F)
#define EOE_HDR_FRAME_OFFSET_OFFSET 6
#define EOE_HDR_FRAME_OFFSET (0x3F << 6)
#define EOE_HDR_FRAME_OFFSET_SET(x) (((x) & 0x3F) << 6)
#define EOE_HDR_FRAME_OFFSET_SET(x) ((uint16_t)(((x) & 0x3F) << 6))
#define EOE_HDR_FRAME_OFFSET_GET(x) (((x) >> 6) & 0x3F)
#define EOE_HDR_FRAME_NO_OFFSET 12
#define EOE_HDR_FRAME_NO (0xF << 12)
#define EOE_HDR_FRAME_NO_SET(x) (((x) & 0xF) << 12)
#define EOE_HDR_FRAME_NO_SET(x) ((uint16_t)(((x) & 0xF) << 12))
#define EOE_HDR_FRAME_NO_GET(x) (((x) >> 12) & 0xF)
/** EOE param */
@ -109,7 +109,7 @@
/** Ethernet address length not including VLAN */
#define EOE_ETHADDR_LENGTH 6
/** IPv4 address length */
#define EOE_IP4_LENGTH sizeof(uint32_t)
#define EOE_IP4_LENGTH 4U /* sizeof(uint32_t) */
/** EOE ip4 address in network order */
struct eoe_ip4_addr {
@ -135,18 +135,18 @@ typedef struct
/** Current RX fragment number */
uint8_t rxfragmentno;
/** Complete RX frame size of current frame */
uint16_t rxframesize;
uint32_t rxframesize;
/** Current RX data offset in frame */
uint16_t rxframeoffset;
uint32_t rxframeoffset;
/** Current RX frame number */
uint16_t rxframeno;
/** Current TX fragment number */
uint8_t txfragmentno;
/** Complete TX frame size of current frame */
uint16_t txframesize;
uint32_t txframesize;
/** Current TX data offset in frame */
uint16_t txframeoffset;
uint32_t txframeoffset;
} _EOEvar;
/** EoE IP request structure */
@ -217,7 +217,7 @@ static void EOE_ip_byte_to_uint32 (uint8_t * byte_ip, eoe_ip4_addr_t * ip)
* @param[out] mac = variable to store mac in, should fit EOE_ETHADDR_LENGTH
* @return 0= if we succeed, -1 if not set
*/
int EOE_get_mac(uint8_t port, uint8_t mac[])
int EOE_ecat_get_mac(uint8_t port, uint8_t mac[])
{
int ret = -1;
int port_ix;
@ -506,7 +506,7 @@ static void EOE_get_ip (void)
uint16_t frameinfo1;
uint8_t port;
uint8_t flags;
uint8_t data_offset;
uint32_t data_offset;
int port_ix;
req_eoembx = (_EOE *) &MBX[0];
@ -518,10 +518,11 @@ static void EOE_get_ip (void)
if(port > EOE_NUMBER_OF_PORTS)
{
DPRINT("Invalid port\n");
frameinfo1 = EOE_HDR_FRAME_PORT_SET(port);
frameinfo1 |= EOE_INIT_RESP;
frameinfo1 |= EOE_HDR_LAST_FRAGMENT;
/* Return error response on given port */
EOE_no_data_response((EOE_HDR_FRAME_PORT_SET(port) |
EOE_INIT_RESP |
EOE_HDR_LAST_FRAGMENT),
EOE_no_data_response(frameinfo1,
EOE_RESULT_UNSPECIFIED_ERROR);
return;
}
@ -539,10 +540,10 @@ static void EOE_get_ip (void)
eoembx = (_EOE *) &MBX[mbxhandle * ESC_MBXSIZE];
eoembx->mbxheader.mbxtype = MBXEOE;
MBXcontrol[mbxhandle].state = MBXstate_outreq;
eoembx->eoeheader.frameinfo1 =
htoes(EOE_HDR_FRAME_TYPE_SET(EOE_GET_IP_PARAM_RESP) |
EOE_HDR_FRAME_PORT_SET(port) |
EOE_HDR_LAST_FRAGMENT);
frameinfo1 = EOE_HDR_FRAME_PORT_SET(port);
frameinfo1 |= EOE_HDR_FRAME_TYPE_SET(EOE_GET_IP_PARAM_RESP);
frameinfo1 |= EOE_HDR_LAST_FRAGMENT;
eoembx->eoeheader.frameinfo1 = htoes(frameinfo1);
eoembx->eoeheader.frameinfo2 = 0;
/* include mac in get ip request */
@ -618,11 +619,10 @@ static void EOE_get_ip (void)
static void EOE_set_ip (void)
{
_EOE *eoembx;
uint16_t eoedatasize;
uint32_t eoedatasize, data_offset;
uint16_t frameinfo1;
uint8_t port;
uint8_t flags;
uint8_t data_offset;
uint16_t result;
int port_ix;
@ -637,10 +637,10 @@ static void EOE_set_ip (void)
{
DPRINT("Invalid port\n");
/* Return error response on given port */
EOE_no_data_response((EOE_HDR_FRAME_PORT_SET(port) |
EOE_INIT_RESP |
EOE_HDR_LAST_FRAGMENT),
EOE_RESULT_UNSPECIFIED_ERROR);
frameinfo1 = EOE_HDR_FRAME_PORT_SET(port);
frameinfo1 |= EOE_INIT_RESP;
frameinfo1 |= EOE_HDR_LAST_FRAGMENT;
EOE_no_data_response(frameinfo1, EOE_RESULT_UNSPECIFIED_ERROR);
return;
}
@ -694,7 +694,7 @@ static void EOE_set_ip (void)
/* dns name included in set ip request? */
if(flags & EOE_PARAM_DNS_NAME_INCLUDE)
{
uint16_t dns_len = MIN((eoedatasize - data_offset), EOE_DNS_NAME_LENGTH);
uint32_t dns_len = MIN((eoedatasize - data_offset), EOE_DNS_NAME_LENGTH);
memcpy(nic_ports[port_ix].dns_name,
&eoembx->data[data_offset],
dns_len);
@ -712,17 +712,17 @@ static void EOE_set_ip (void)
* you typically set the IP for the TCP/IP stack */
if(eoe_cfg->store_ethernet_settings != NULL)
{
result = eoe_cfg->store_ethernet_settings();
result = (uint16_t)eoe_cfg->store_ethernet_settings();
}
else
{
result = EOE_RESULT_NO_IP_SUPPORT;
}
}
EOE_no_data_response((EOE_HDR_FRAME_PORT_SET(port) |
EOE_INIT_RESP |
EOE_HDR_LAST_FRAGMENT),
result);
frameinfo1 = EOE_HDR_FRAME_PORT_SET(port);
frameinfo1 |= EOE_INIT_RESP;
frameinfo1 |= EOE_HDR_LAST_FRAGMENT;
EOE_no_data_response(frameinfo1, result);
}
/** EoE receive fragment handler.
@ -731,14 +731,14 @@ static void EOE_receive_fragment (void)
{
_EOE *eoembx;
eoembx = (_EOE *) &MBX[0];
uint16_t eoedatasize = etohs(eoembx->mbxheader.length) - ESC_EOEHSIZE;
uint32_t eoedatasize = etohs(eoembx->mbxheader.length) - ESC_EOEHSIZE;
uint16_t frameinfo1 = etohs(eoembx->eoeheader.frameinfo1);
uint16_t frameinfo2 = etohs(eoembx->eoeheader.frameinfo2);
/* Capture error case */
if(EOEvar.rxfragmentno != EOE_HDR_FRAG_NO_GET(frameinfo2))
{
DPRINT("Unexpected fragment number %d, expected: %d\n",
DPRINT("Unexpected fragment number %"PRIu32", expected: %"PRIu32"\n",
EOE_HDR_FRAG_NO_GET(frameinfo2), EOEvar.rxfragmentno);
/* Clean up existing saved data */
if(EOEvar.rxfragmentno != 0)
@ -763,22 +763,28 @@ static void EOE_receive_fragment (void)
EOEvar.rxframeoffset = 0;
EOEvar.rxframeno = EOE_HDR_FRAME_NO_GET(frameinfo2);
}
else
{
DPRINT("Receive buffer is invalid\n");
EOE_init_rx ();
return;
}
}
/* In frame fragment received */
else
{
uint16_t offset = (EOE_HDR_FRAME_OFFSET_GET(frameinfo2) << 5);
uint32_t offset = (EOE_HDR_FRAME_OFFSET_GET(frameinfo2) << 5);
/* Validate received fragment */
if(EOEvar.rxframeno != EOE_HDR_FRAME_NO_GET(frameinfo2))
{
DPRINT("Unexpected frame number %d, expected: %d\n",
DPRINT("Unexpected frame number %"PRIu32", expected: %"PRIu32"\n",
EOE_HDR_FRAME_NO_GET(frameinfo2), EOEvar.rxframeno);
EOE_init_rx ();
return;
}
else if(EOEvar.rxframeoffset != offset)
{
DPRINT("Unexpected frame offset %d, expected: %d\n",
DPRINT("Unexpected frame offset %"PRIu32", expected: %"PRIu32"\n",
offset, EOEvar.rxframeoffset);
EOE_init_rx ();
return;
@ -806,7 +812,7 @@ static void EOE_receive_fragment (void)
/* Remove time stamp, TODO support for time stamp? */
if(EOE_HDR_TIME_APPEND_GET(frameinfo1))
{
EOEvar.rxframeoffset -= 4;
EOEvar.rxframeoffset -= 4U;
}
EOEvar.rxebuf.len = EOEvar.rxframeoffset;
eoe_cfg->handle_recv_buffer(EOE_HDR_FRAME_PORT_GET(frameinfo1),
@ -824,7 +830,7 @@ static void EOE_send_fragment ()
_EOE *eoembx;
uint8_t mbxhandle;
int len;
int len_to_send;
uint32_t len_to_send;
uint16_t frameinfo1;
uint16_t frameinfo2;
static uint8_t frameno = 0;
@ -836,7 +842,7 @@ static void EOE_send_fragment ()
len = eoe_cfg->fetch_send_buffer(0, &EOEvar.txebuf);
if(len > 0)
{
EOEvar.txframesize = len;
EOEvar.txframesize = (uint32_t)len;
}
else
{
@ -848,7 +854,7 @@ static void EOE_send_fragment ()
mbxhandle = ESC_claimbuffer ();
if (mbxhandle)
{
len_to_send = EOEvar.txframesize - EOEvar.txframeoffset;
len_to_send = (EOEvar.txframesize - EOEvar.txframeoffset);
if((len_to_send + ESC_EOEHSIZE + ESC_MBXHSIZE) > ESC_MBXSIZE)
{
/* Adjust to len in whole 32 octet blocks to fit specification*/
@ -866,23 +872,26 @@ static void EOE_send_fragment ()
frameinfo1 = 0;
}
uint16_t tempframe2;
/* Set fragment number */
frameinfo2 = EOE_HDR_FRAG_NO_SET(EOEvar.txfragmentno);
/* Set complete size for fragment 0 or offset for in frame fragments */
if(EOEvar.txfragmentno > 0)
{
frameinfo2 |= (EOE_HDR_FRAME_OFFSET_SET((EOEvar.txframeoffset >> 5)));
tempframe2 = EOE_HDR_FRAME_OFFSET_SET((EOEvar.txframeoffset >> 5));
frameinfo2 |= tempframe2;
}
else
{
frameinfo2 |=
(EOE_HDR_FRAME_OFFSET_SET(((EOEvar.txframesize + 31) >> 5)));
tempframe2 = EOE_HDR_FRAME_OFFSET_SET(((EOEvar.txframesize + 31) >> 5));
frameinfo2 |= tempframe2;
frameno++;
}
/* Set frame number */
frameinfo2 = frameinfo2 | EOE_HDR_FRAME_NO_SET(frameno);
tempframe2 = EOE_HDR_FRAME_NO_SET(frameno);
frameinfo2 |= tempframe2;
eoembx = (_EOE *) &MBX[mbxhandle * ESC_MBXSIZE];
eoembx->mbxheader.length = htoes (len_to_send + ESC_EOEHSIZE);
@ -904,7 +913,7 @@ static void EOE_send_fragment ()
else
{
EOEvar.txframeoffset += len_to_send;
EOEvar.txfragmentno += 1;
EOEvar.txfragmentno++;
}
if(eoe_cfg->fragment_sent_event != NULL)
{

View File

@ -50,7 +50,7 @@ static _FOEvar FOEvar;
* @return 0= if we succeed, FOE_ERR_NOTFOUND something wrong with filename or
* password
*/
static int FOE_fopen (char *name, uint8_t num_chars, uint32_t pass, uint8_t op)
static uint32_t FOE_fopen (char *name, uint8_t num_chars, uint32_t pass, uint8_t op)
{
uint32_t i;
@ -118,9 +118,9 @@ static int FOE_fopen (char *name, uint8_t num_chars, uint32_t pass, uint8_t op)
* @return Number of copied bytes.
*/
static uint16_t FOE_fread (uint8_t * data, uint16_t maxlength)
static uint32_t FOE_fread (uint8_t * data, uint32_t maxlength)
{
uint16_t ncopied = 0;
uint32_t ncopied = 0;
while (maxlength && (FOEvar.fend - FOEvar.fposition))
{
@ -144,9 +144,9 @@ static uint16_t FOE_fread (uint8_t * data, uint16_t maxlength)
* @return Number of copied bytes.
*/
static uint16_t FOE_fwrite (uint8_t *data, uint16_t length)
static uint32_t FOE_fwrite (uint8_t *data, uint32_t length)
{
uint16_t ncopied = 0;
uint32_t ncopied = 0;
uint32_t failed = 0;
DPRINT("FOE_fwrite\n");
@ -162,12 +162,19 @@ static uint16_t FOE_fwrite (uint8_t *data, uint16_t length)
foe_file->address_offset += foe_cfg->buffer_size;
}
FOEvar.fposition++;
ncopied++;
if(failed)
{
DPRINT("Failed FOE_fwrite ncopied=%"PRIu32"\n", ncopied);
}
else
{
ncopied++;
}
}
foe_file->total_size += ncopied;
DPRINT("FOE_fwrite END with : %d\n",ncopied);
DPRINT("FOE_fwrite END with : %"PRIu32"\n",ncopied);
return ncopied;
}
@ -227,7 +234,7 @@ static void FOE_abort (uint32_t code)
}
/* Nothing we can do if we can't get an outbound mailbox. */
}
DPRINT("FOE_abort: 0x%X\n", code);
DPRINT("FOE_abort: 0x%"PRIX32"\n", code);
FOE_init ();
}
@ -242,10 +249,10 @@ static void FOE_abort (uint32_t code)
* @return Number of data bytes written or an error number. Error numbers
* will be greater than FOE_DATA_SIZE.
*/
static int FOE_send_data_packet ()
static uint32_t FOE_send_data_packet ()
{
_FOE *foembx;
uint16_t data_len;
uint32_t data_len;
uint8_t mbxhandle;
mbxhandle = ESC_claimbuffer ();
@ -273,7 +280,7 @@ static int FOE_send_data_packet ()
* @return 0= or error number.
*/
static int FOE_send_ack ()
static uint32_t FOE_send_ack ()
{
_FOE *foembx;
uint8_t mbxhandle;
@ -309,9 +316,9 @@ static int FOE_send_ack ()
static void FOE_read ()
{
_FOE *foembx;
uint32_t data_len;
uint32_t password;
int res;
uint32_t res;
uint8_t data_len;
if (FOEvar.foestate != FOE_READY)
{
@ -322,7 +329,7 @@ static void FOE_read ()
FOE_init ();
foembx = (_FOE *) &MBX[0];
/* Get the length of the file name in octets. */
data_len = etohs (foembx->mbxheader.length) - ESC_FOEHSIZE;
data_len = (uint8_t)(etohs (foembx->mbxheader.length) - ESC_FOEHSIZE);
password = etohl (foembx->foeheader.password);
res = FOE_fopen (foembx->filename, data_len, password, FOE_OP_RRQ);
@ -333,7 +340,7 @@ static void FOE_read ()
* Attempt to send the packet
*/
res = FOE_send_data_packet ();
if (res <= (int)ESC_FOE_DATA_SIZE)
if (res <= ESC_FOE_DATA_SIZE)
{
FOEvar.foestate = FOE_WAIT_FOR_ACK;
}
@ -353,7 +360,7 @@ static void FOE_read ()
*/
static void FOE_ack ()
{
int res;
uint32_t res;
/* Make sure we're able to take this. */
if (FOEvar.foestate == FOE_WAIT_FOR_FINAL_ACK)
@ -368,7 +375,7 @@ static void FOE_ack ()
return;
}
res = FOE_send_data_packet ();
if (res < (int)ESC_FOE_DATA_SIZE)
if (res < ESC_FOE_DATA_SIZE)
{
FOEvar.foestate = FOE_WAIT_FOR_FINAL_ACK;
}
@ -386,9 +393,9 @@ static void FOE_ack ()
static void FOE_write ()
{
_FOE *foembx;
uint32_t data_len;
uint32_t password;
int res;
uint32_t res;
uint8_t data_len;
if (FOEvar.foestate != FOE_READY)
{
@ -398,7 +405,7 @@ static void FOE_write ()
FOE_init ();
foembx = (_FOE *) &MBX[0];
data_len = etohs (foembx->mbxheader.length) - ESC_FOEHSIZE;
data_len = (uint8_t)(etohs (foembx->mbxheader.length) - ESC_FOEHSIZE);
password = etohl (foembx->foeheader.password);
/* Get an address we can write the file to, if possible. */
@ -429,8 +436,8 @@ static void FOE_data ()
{
_FOE *foembx;
uint32_t packet;
uint16_t data_len, ncopied;
int res;
uint32_t data_len, ncopied;
uint32_t res;
if(FOEvar.foestate != FOE_WAIT_FOR_DATA)
{
@ -444,7 +451,9 @@ static void FOE_data ()
if (packet != FOEvar.foepacket)
{
DPRINT("FOE_data packet error, packet: %d, foeheader.packet: %d\n",packet,FOEvar.foepacket);
DPRINT("FOE_data packet error, packet: %"PRIu32", foeheader.packet: %"PRIu32"\n",
packet,
FOEvar.foepacket);
FOE_abort (FOE_ERR_PACKETNO);
}
else if (data_len == 0)
@ -472,7 +481,7 @@ static void FOE_data ()
DPRINT("FOE_data data_len == FOE_DATA_SIZE\n");
if (ncopied != data_len)
{
DPRINT("FOE_data only %d of %d copied\n",ncopied, data_len);
DPRINT("FOE_data only %"PRIu32" of %"PRIu32" copied\n",ncopied, data_len);
FOE_abort (FOE_ERR_PROGERROR);
}
res = FOE_send_ack ();

View File

@ -16,7 +16,7 @@
#include <stdlib.h>
#include <unistd.h>
#define BIT(x) 1 << (x)
#define BIT(x) (1U << (x))
#define ESC_CMD_SERIAL_WRITE 0x02
#define ESC_CMD_SERIAL_READ 0x03
@ -59,15 +59,15 @@ static int lan9252 = -1;
static void lan9252_write_32 (uint16_t address, uint32_t val)
{
uint8_t data[7];
int n;
ssize_t n;
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);
data[1] = (uint8_t)((address >> 8) & 0xFF);
data[2] = (uint8_t)(address & 0xFF);
data[3] = (uint8_t)(val & 0xFF);
data[4] = (uint8_t)((val >> 8) & 0xFF);
data[5] = (uint8_t)((val >> 16) & 0xFF);
data[6] = (uint8_t)((val >> 24) & 0xFF);
/* Write data */
n = write (lan9252, data, sizeof(data));
@ -80,17 +80,17 @@ static uint32_t lan9252_read_32 (uint32_t address)
uint8_t data[2];
uint8_t result[4];
uint16_t lseek_addr;
int n;
ssize_t n;
data[0] = ((address >>8) & 0xFF);
data[1] = (address & 0xFF);
lseek_addr=((uint16_t)data[0] << 8) | data[1];
lseek (lan9252, lseek_addr, SEEK_SET);
lseek_addr=(uint16_t)((data[0] << 8) | data[1]);
lseek (lan9252, lseek_addr, SEEK_SET);
n = read (lan9252, result, sizeof(result));
(void)n;
return ((result[3] << 24) |
return (uint32_t)((result[3] << 24) |
(result[2] << 16) |
(result[1] << 8) |
result[0]);
@ -101,7 +101,9 @@ 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);
value = ESC_CSR_CMD_READ;
value |= (uint32_t)ESC_CSR_CMD_SIZE(len);
value |= address;
lan9252_write_32(ESC_CSR_CMD_REG, value);
do
@ -120,7 +122,9 @@ static void ESC_write_csr (uint16_t address, void *buf, uint16_t len)
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);
value = ESC_CSR_CMD_WRITE;
value |= (uint32_t)ESC_CSR_CMD_SIZE(len);
value |= address;
lan9252_write_32(ESC_CSR_CMD_REG, value);
do
@ -137,10 +141,10 @@ static void ESC_read_pram (uint16_t address, void *buf, uint16_t len)
uint16_t byte_offset = 0;
uint8_t fifo_cnt, first_byte_position, temp_len;
uint8_t *buffer;
int i, array_size, size;
size_t i, array_size, size;
float quotient,remainder;
uint32_t temp;
int n;
ssize_t n;
value = ESC_PRAM_CMD_ABORT;
lan9252_write_32(ESC_PRAM_RD_CMD_REG, value);
@ -150,7 +154,7 @@ static void ESC_read_pram (uint16_t address, void *buf, uint16_t len)
value = lan9252_read_32(ESC_PRAM_RD_CMD_REG);
}while(value & ESC_PRAM_CMD_BUSY);
value = ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address);
value = (uint32_t)(ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address));
lan9252_write_32(ESC_PRAM_RD_ADDR_LEN_REG, value);
value = ESC_PRAM_CMD_BUSY;
@ -162,7 +166,7 @@ static void ESC_read_pram (uint16_t address, void *buf, uint16_t len)
}while((value & ESC_PRAM_CMD_AVAIL) == 0);
/* Fifo count */
fifo_cnt = ESC_PRAM_CMD_CNT(value);
fifo_cnt = (uint8_t)ESC_PRAM_CMD_CNT(value);
/* Read first value from FIFO */
value = lan9252_read_32(ESC_PRAM_RD_FIFO_REG);
@ -172,27 +176,27 @@ static void ESC_read_pram (uint16_t address, void *buf, uint16_t len)
* 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);
temp_len = ((4 - first_byte_position) > len) ? (uint8_t)len : (uint8_t)(4 - first_byte_position);
memcpy(temp_buf ,((uint8_t *)&value + first_byte_position), temp_len);
len -= temp_len;
byte_offset += temp_len;
len = (uint16_t)(len - temp_len);
byte_offset = (uint16_t)(byte_offset + temp_len);
/* Continue reading until we have read len */
if (len > 0){
quotient = len/4;
remainder = len%4;
quotient = (float)(len/4);
remainder = (float)(len%4);
if (remainder == 0)
array_size = quotient;
array_size = (size_t)quotient;
else
array_size = quotient+1;
array_size = (size_t)quotient+1;
size = 4*array_size;
buffer = (uint8_t *)malloc(size);
buffer[0] = size;
buffer[0] = (uint8_t)size;
memset(buffer,0,size);
lseek (lan9252, ESC_PRAM_RD_FIFO_REG, SEEK_SET);
@ -203,13 +207,13 @@ static void ESC_read_pram (uint16_t address, void *buf, uint16_t len)
{
for (i=0; i<size; i=i+4) {
temp_len = (len > 4) ? 4: len;
temp_len = (len > 4) ? 4: (uint8_t)len;
temp = buffer[i] | (buffer[i+1] << 8) | (buffer[i+2] << 16) | (buffer[i+3] << 24);
temp = (uint32_t)(buffer[i] | (buffer[i+1] << 8) | (buffer[i+2] << 16) | (buffer[i+3] << 24));
memcpy(temp_buf + byte_offset ,&temp, temp_len);
fifo_cnt--;
len -= temp_len;
byte_offset += temp_len;
len = (uint16_t)(len - temp_len);
byte_offset = (uint16_t)(byte_offset + temp_len);
}
}
free(buffer);
@ -224,9 +228,9 @@ static void ESC_write_pram (uint16_t address, void *buf, uint16_t len)
uint16_t byte_offset = 0;
uint8_t fifo_cnt, first_byte_position, temp_len;
uint8_t *buffer;
int i, array_size, size;
size_t i, array_size, size;
float quotient,remainder;
int n;
ssize_t n;
value = ESC_PRAM_CMD_ABORT;
lan9252_write_32(ESC_PRAM_WR_CMD_REG, value);
@ -236,7 +240,7 @@ static void ESC_write_pram (uint16_t address, void *buf, uint16_t len)
value = lan9252_read_32(ESC_PRAM_WR_CMD_REG);
}while(value & ESC_PRAM_CMD_BUSY);
value = ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address);
value = (uint32_t)(ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address));
lan9252_write_32(ESC_PRAM_WR_ADDR_LEN_REG, value);
value = ESC_PRAM_CMD_BUSY;
@ -248,37 +252,37 @@ static void ESC_write_pram (uint16_t address, void *buf, uint16_t len)
}while((value & ESC_PRAM_CMD_AVAIL) == 0);
/* Fifo count */
fifo_cnt = ESC_PRAM_CMD_CNT(value);
fifo_cnt = (uint8_t)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);
temp_len = ((4 - first_byte_position) > len) ? (uint8_t)len : (uint8_t)(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;
len = (uint16_t)(len - temp_len);
byte_offset = (uint16_t)(byte_offset + temp_len);
fifo_cnt--;
if (len > 0){
quotient = len/4;
remainder = len%4;
remainder = (float)(len%4);
if (remainder == 0)
array_size = quotient;
array_size = (size_t)quotient;
else
array_size = quotient+1;
array_size = (size_t)quotient+1;
size = 3+4*array_size;
buffer = (uint8_t *)malloc(size);
buffer[0] = size;
buffer[0] = (uint8_t)size;
memset(buffer,0,size);
buffer[0] = ESC_CMD_SERIAL_WRITE;
@ -287,17 +291,17 @@ static void ESC_write_pram (uint16_t address, void *buf, uint16_t len)
while(len > 0)
{
for (i=3; i<size; i=i+4) {
temp_len = (len > 4) ? 4 : len;
temp_len = (len > 4) ? 4 : (uint8_t)len;
memcpy((uint8_t *)&value, (temp_buf + byte_offset), temp_len);
buffer[i] = (value & 0xFF);
buffer[i+1] = ((value >> 8) & 0xFF);
buffer[i+2] = ((value >> 16) & 0xFF);
buffer[i+3] = ((value >> 24) & 0xFF);
buffer[i] = (uint8_t)(value & 0xFF);
buffer[i+1] = (uint8_t)((value >> 8) & 0xFF);
buffer[i+2] = (uint8_t)((value >> 16) & 0xFF);
buffer[i+3] = (uint8_t)((value >> 24) & 0xFF);
fifo_cnt--;
len -= temp_len;
byte_offset += temp_len;
len = (uint16_t)(len - temp_len);
byte_offset= (uint16_t)(byte_offset + temp_len);
}
}
n = write (lan9252, buffer, size);
@ -351,9 +355,9 @@ void ESC_read (uint16_t address, void *buf, uint16_t len)
ESC_read_csr(address, temp_buf, size);
/* next address */
len -= size;
temp_buf += size;
address += size;
len = (uint16_t)(len - size);
temp_buf = (uint8_t *)(temp_buf + size);
address = (uint16_t)(address + size);
}
}
/* To mimic the ET1100 always providing AlEvent on every read or write */
@ -406,9 +410,9 @@ void ESC_write (uint16_t address, void *buf, uint16_t len)
ESC_write_csr(address, temp_buf, size);
/* next address */
len -= size;
temp_buf += size;
address += size;
len = (uint16_t)(len - size);
temp_buf = (uint8_t *)(temp_buf + size);
address = (uint16_t)(address + size);
}
}

View File

@ -0,0 +1,602 @@
/*
* 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 for LAN9252 through BCM2835 SPI on Raspberry PI.
*
* Function to read and write commands to the ESC. Used to read/write ESC
* registers and memory.
*/
#include "esc.h"
#include "esc_hw.h"
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <bcm2835.h>
#define BIT(x) (1U << (x))
#define ESC_CMD_SERIAL_WRITE 0x02
#define ESC_CMD_SERIAL_READ 0x03
#define ESC_CMD_RESET_CTL 0x01F8 // reset register
#define ESC_CMD_HW_CFG 0x0074 // hardware configuration register
#define ESC_CMD_BYTE_TEST 0x0064 // byte order test register
#define ESC_CMD_ID_REV 0x0050 // chip ID and revision
#define ESC_CMD_IRQ_CFG 0x0054 // interrupt configuration
#define ESC_CMD_INT_EN 0x005C // interrupt enable
#define ESC_RESET_DIGITAL 0x00000001
#define ESC_RESET_ETHERCAT 0x00000040
#define ESC_RESET_CTRL_RST (ESC_RESET_DIGITAL & ESC_RESET_ETHERCAT)
#define ESC_HW_CFG_READY 0x08000000
#define ESC_BYTE_TEST_OK 0x87654321
#define ESC_PRAM_RD_FIFO_REG 0x0000
#define ESC_PRAM_WR_FIFO_REG 0x0020
#define ESC_PRAM_RD_ADDR_LEN_REG 0x0308
#define ESC_PRAM_RD_CMD_REG 0x030C
#define ESC_PRAM_WR_ADDR_LEN_REG 0x0310
#define ESC_PRAM_WR_CMD_REG 0x0314
#define ESC_PRAM_CMD_BUSY 0x80000000
#define ESC_PRAM_CMD_ABORT 0x40000000
#define ESC_PRAM_CMD_AVAIL 0x00000001
#define ESC_PRAM_CMD_CNT(x) (((x) >> 8) & 0x1F)
#define ESC_PRAM_SIZE(x) ((x) << 16)
#define ESC_PRAM_ADDR(x) ((x) << 0)
#define ESC_CSR_DATA_REG 0x0300
#define ESC_CSR_CMD_REG 0x0304
#define ESC_CSR_CMD_BUSY 0x80000000
#define ESC_CSR_CMD_READ (0x80000000 | 0x40000000)
#define ESC_CSR_CMD_WRITE 0x80000000
#define ESC_CSR_CMD_SIZE(x) ((x) << 16)
/* bcm2835 spi single write */
static void bcm2835_spi_write_32 (uint16_t address, uint32_t val)
{
char 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);
/* Write data */
bcm2835_spi_transfern(data, 7);
}
/* bcm2835 spi single read */
static uint32_t bcm2835_spi_read_32 (uint16_t address)
{
char data[7];
data[0] = ESC_CMD_SERIAL_READ;
data[1] = ((address >> 8) & 0xFF);
data[2] = (address & 0xFF);
/* Read data */
bcm2835_spi_transfern(data, 7);
return ((data[6] << 24) |
(data[5] << 16) |
(data[4] << 8) |
data[3]);
}
/* 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);
bcm2835_spi_write_32(ESC_CSR_CMD_REG, value);
do
{
value = bcm2835_spi_read_32(ESC_CSR_CMD_REG);
} while(value & ESC_CSR_CMD_BUSY);
value = bcm2835_spi_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);
bcm2835_spi_write_32(ESC_CSR_DATA_REG, value);
value = (ESC_CSR_CMD_WRITE | ESC_CSR_CMD_SIZE(len) | address);
bcm2835_spi_write_32(ESC_CSR_CMD_REG, value);
do
{
value = bcm2835_spi_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;
uint16_t quotient, remainder, byte_offset = 0;
uint8_t fifo_cnt, fifo_size, fifo_range, first_byte_position, temp_len;
uint8_t *buffer = NULL;
int i, size;
bcm2835_spi_write_32(ESC_PRAM_RD_CMD_REG, ESC_PRAM_CMD_ABORT);
do
{
value = bcm2835_spi_read_32(ESC_PRAM_RD_CMD_REG);
}while(value & ESC_PRAM_CMD_BUSY);
bcm2835_spi_write_32(ESC_PRAM_RD_ADDR_LEN_REG, (ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address)));
bcm2835_spi_write_32(ESC_PRAM_RD_CMD_REG, ESC_PRAM_CMD_BUSY);
/* Find out first byte position and adjust the copy from that
* according to LAN9252 datasheet and MicroChip SDK code
*/
first_byte_position = (address & 0x03);
/* Transfer data */
while (len > 0)
{
/* Wait for read availabiliy */
if (byte_offset > 0)
{
quotient = len/4;
remainder = len - quotient*4;
}
else
{
quotient = (len + first_byte_position)/4;
remainder = (len + first_byte_position) - quotient*4;
}
if (remainder != 0)
{
quotient++;
}
fifo_range = MIN(quotient,16);
do
{
value = bcm2835_spi_read_32(ESC_PRAM_RD_CMD_REG);
}while(!(value & ESC_PRAM_CMD_AVAIL) || (ESC_PRAM_CMD_CNT(value) < fifo_range));
/* Fifo size */
fifo_size = ESC_PRAM_CMD_CNT(value);
/* Transfer data size */
size = 3+4*fifo_size;
/* Allocate buffer */
buffer = (uint8_t *)realloc(buffer, size);
/* Reset fifo count */
fifo_cnt = fifo_size;
/* Reset buffer */
memset(buffer,0,size);
buffer[0] = ESC_CMD_SERIAL_READ;
buffer[1] = ((ESC_PRAM_RD_FIFO_REG >>8) & 0xFF);
buffer[2] = ( ESC_PRAM_RD_FIFO_REG & 0xFF);
/* Transfer batch of data */
bcm2835_spi_transfern((char *)buffer, size);
i = 3;
while (fifo_cnt > 0 && len > 0)
{
value = buffer[i] | (buffer[i+1] << 8) | (buffer[i+2] << 16) | (buffer[i+3] << 24);
if (byte_offset > 0)
{
temp_len = (len > 4) ? 4: len;
memcpy(temp_buf + byte_offset ,&value, temp_len);
}
else
{
temp_len = (len > (4 - first_byte_position)) ? (4 - first_byte_position) : len;
memcpy(temp_buf ,((uint8_t *)&value + first_byte_position), temp_len);
}
i += 4;
fifo_cnt--;
len -= temp_len;
byte_offset += temp_len;
}
}
free(buffer);
}
/* 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;
uint16_t quotient, remainder, byte_offset = 0;
uint8_t fifo_cnt, fifo_size, fifo_range, first_byte_position, temp_len;
uint8_t *buffer = NULL;
int i, size;
bcm2835_spi_write_32(ESC_PRAM_WR_CMD_REG, ESC_PRAM_CMD_ABORT);
do
{
value = bcm2835_spi_read_32(ESC_PRAM_WR_CMD_REG);
}while(value & ESC_PRAM_CMD_BUSY);
bcm2835_spi_write_32(ESC_PRAM_WR_ADDR_LEN_REG, (ESC_PRAM_SIZE(len) | ESC_PRAM_ADDR(address)));
bcm2835_spi_write_32(ESC_PRAM_WR_CMD_REG, ESC_PRAM_CMD_BUSY);
/* Find out first byte position and adjust the copy from that
* according to LAN9252 datasheet and MicroChip SDK code
*/
first_byte_position = (address & 0x03);
/* Transfer data */
while (len > 0)
{
/* Wait for write availabiliy */
if (byte_offset > 0)
{
quotient = len/4;
remainder = len - quotient*4;
}
else
{
quotient = (len + first_byte_position)/4;
remainder = (len + first_byte_position) - quotient*4;
}
if (remainder != 0)
{
quotient++;
}
fifo_range = MIN(quotient,16);
do
{
value = bcm2835_spi_read_32(ESC_PRAM_WR_CMD_REG);
}while(!(value & ESC_PRAM_CMD_AVAIL) || (ESC_PRAM_CMD_CNT(value) < fifo_range));
/* Fifo size */
fifo_size = ESC_PRAM_CMD_CNT(value);
/* Transfer data size */
size = 3+4*fifo_size;
/* Allocate buffer */
buffer = (uint8_t *)realloc(buffer, size);
/* Reset fifo count */
fifo_cnt = fifo_size;
/* Reset buffer */
memset(buffer,0,size);
buffer[0] = ESC_CMD_SERIAL_WRITE;
buffer[1] = ((ESC_PRAM_WR_FIFO_REG >> 8) & 0xFF);
buffer[2] = (ESC_PRAM_WR_FIFO_REG & 0xFF);
i = 3;
while (fifo_cnt > 0 && len > 0)
{
value = 0;
if (byte_offset > 0)
{
temp_len = (len > 4) ? 4: len;
memcpy(&value, (temp_buf + byte_offset), temp_len);
}
else
{
temp_len = (len > (4 - first_byte_position)) ? (4 - first_byte_position) : len;
memcpy(((uint8_t *)&value + first_byte_position), temp_buf, temp_len);
}
buffer[i] = (value & 0xFF);
buffer[i+1] = ((value >> 8) & 0xFF);
buffer[i+2] = ((value >> 16) & 0xFF);
buffer[i+3] = ((value >> 24) & 0xFF);
i += 4;
fifo_cnt--;
len -= temp_len;
byte_offset += temp_len;
}
/* Transfer batch of data */
bcm2835_spi_transfern((char *)buffer, size);
}
free(buffer);
}
/** 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 esc_cfg_t * config)
{
bool rpi4 = false, cs1 = false;
uint32_t value;
uint32_t counter = 0;
uint32_t timeout = 1000; // wait 100msec
const char * user_arg = (char *)config->user_arg;
size_t arg_len = strlen(user_arg)+1;
char * arg_str = (char *)calloc(arg_len, sizeof(char));
strncpy(arg_str,user_arg,arg_len);
char * delim = " ,.-";
char * token = strtok(arg_str,delim);
// parse user arguments
while (token != NULL)
{
if (strncmp(token,"cs1",3) == 0)
{
cs1 = true; // select CS1 pin
}
else if (strncmp(token,"rpi4",4) == 0)
{
rpi4 = true; // select clock divider for raspberry pi 4 or newer
}
token = strtok(NULL,delim);
}
free(arg_str);
// start initialization
if (bcm2835_init())
{
if (bcm2835_spi_begin())
{
// Set SPI bit order
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
// Set SPI data mode BCM2835_SPI_MODE0 = 0, CPOL = 0, CPHA = 0,
// Clock idle low, data is clocked in on rising edge, output data (change) on falling edge
bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
if (rpi4)
{
// Raspberry 4 due to a higher CPU speed this value is to change to: BCM2835_SPI_CLOCK_DIVIDER_32
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_32);
DPRINT("bcm2835_spi_setClockDivider set to 32 \n");
}
else
{
// Set SPI clock speed BCM2835_SPI_CLOCK_DIVIDER_16 = 16, 16 = 64ns = 15.625MHz
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_16);
DPRINT("bcm2835_spi_setClockDivider set to 16 \n");
}
if (cs1)
{
// Enable management of CS1 pin
bcm2835_spi_chipSelect(BCM2835_SPI_CS1);
// Enable CS1 and set polarity
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS1, LOW);
DPRINT("bcm2835_spi_chipSelect set to CS1 \n");
}
else
{
// Enable management of CS0 pin
bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
// enable CS0 and set polarity
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);
DPRINT("bcm2835_spi_chipSelect set to CS0 \n");
}
// Reset the ecat core here due to evb-lan9252-digio not having any GPIO for that purpose.
bcm2835_spi_write_32(ESC_CMD_RESET_CTL,ESC_RESET_CTRL_RST);
// Wait until reset command has been executed
do
{
usleep(100);
counter++;
value = bcm2835_spi_read_32(ESC_CMD_RESET_CTL);
} while ((value & ESC_RESET_CTRL_RST) && (counter < timeout));
// Perform byte test
do
{
usleep(100);
counter++;
value = bcm2835_spi_read_32(ESC_CMD_BYTE_TEST);
} while ((value != ESC_BYTE_TEST_OK) && (counter < timeout));
// Check hardware is ready
do
{
usleep(100);
counter++;
value = bcm2835_spi_read_32(ESC_CMD_HW_CFG);
} while (!(value & ESC_HW_CFG_READY) && (counter < timeout));
// Check if timeout occured
if (counter < timeout)
{
// Read the chip identification and revision
value = bcm2835_spi_read_32(ESC_CMD_ID_REV);
DPRINT("Detected chip %x Rev %u \n", ((value >> 16) & 0xFFFF), (value & 0xFFFF));
// Set AL event mask
value = (ESCREG_ALEVENT_CONTROL |
ESCREG_ALEVENT_SMCHANGE |
ESCREG_ALEVENT_SM0 |
ESCREG_ALEVENT_SM1 );
ESC_ALeventmaskwrite(value);
}
else
{
DPRINT("Timeout occurred during reset \n");
bcm2835_spi_end();
bcm2835_close();
}
}
else
{
DPRINT("bcm2835_spi_begin failed. Are you running as root?\n");
bcm2835_close();
}
}
else
{
DPRINT("bcm2835_init failed. Are you running as root?\n");
}
}
void ESC_interrupt_enable (uint32_t mask)
{
// Enable interrupt for SYNC0 or SM2 or SM3
uint32_t user_int_mask = ESCREG_ALEVENT_DC_SYNC0 |
ESCREG_ALEVENT_SM2 |
ESCREG_ALEVENT_SM3;
if (mask & user_int_mask)
{
ESC_ALeventmaskwrite(ESC_ALeventmaskread() | (mask & user_int_mask));
}
// Set LAN9252 interrupt pin driver as push-pull active high
bcm2835_spi_write_32(ESC_CMD_IRQ_CFG, 0x00000111);
// Enable LAN9252 interrupt
bcm2835_spi_write_32(ESC_CMD_INT_EN, 0x00000001);
}
void ESC_interrupt_disable (uint32_t mask)
{
// Enable interrupt for SYNC0 or SM2 or SM3
uint32_t user_int_mask = ESCREG_ALEVENT_DC_SYNC0 |
ESCREG_ALEVENT_SM2 |
ESCREG_ALEVENT_SM3;
if (mask & user_int_mask)
{
// Disable interrupt from SYNC0
ESC_ALeventmaskwrite(ESC_ALeventmaskread() & ~(mask & user_int_mask));
}
// Disable LAN9252 interrupt
bcm2835_spi_write_32(ESC_CMD_INT_EN, 0x00000000);
}

View File

@ -0,0 +1,17 @@
/*
* 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__
void ESC_interrupt_enable (uint32_t mask);
void ESC_interrupt_disable (uint32_t mask);
#endif

View File

@ -10,7 +10,7 @@
* Function to read and write commands to the ESC. Used to read/write ESC
* registers and memory.
*/
#include <kern.h>
#include <kern/kern.h>
#include <bsp.h>
#include <xmc4.h>
#include <eru.h>
@ -242,8 +242,8 @@ static void ecat_isr (void * arg)
CC_ATOMIC_SET(ESCvar.ALevent, etohl(ecat0->AL_EVENT_REQ));
CC_ATOMIC_SET(ESCvar.Time, etohl(ecat0->READMode_DC_SYS_TIME[0]));
/* Handle SM2 interrupt */
if(ESCvar.ALevent & ESCREG_ALEVENT_SM2)
/* Handle SM2 & SM3 interrupt */
if(ESCvar.ALevent & (ESCREG_ALEVENT_SM2 | ESCREG_ALEVENT_SM3))
{
/* Is DC active or not */
if(ESCvar.dcsync == 0)

View File

@ -11,7 +11,7 @@
#ifndef __esc_hw__
#define __esc_hw__
#include <kern.h>
#include <kern/kern.h>
/* ================================================================================ */
/* ================ ECAT [ECAT0] ================ */
/* ================================================================================ */

View File

@ -301,7 +301,7 @@ void PDI_Isr(void)
alevent = bsp_read_word_isr(escHwPruIcssHandle,ESCREG_ALEVENT);
CC_ATOMIC_SET(ESCvar.ALevent, etohs(alevent));
if(ESCvar.ALevent & ESCREG_ALEVENT_SM2)
if(ESCvar.ALevent & (ESCREG_ALEVENT_SM2 & ESCREG_ALEVENT_SM3))
{
DIG_process(DIG_PROCESS_OUTPUTS_FLAG |
DIG_PROCESS_APP_HOOK_FLAG |

View File

@ -14,6 +14,7 @@ extern "C"
#include <assert.h>
#include <stdint.h>
#include <stddef.h>
#include <inttypes.h>
#include <sys/param.h>
#ifdef __linux__
#include <endian.h>
@ -32,8 +33,10 @@ extern "C"
#define CC_PACKED_BEGIN
#define CC_PACKED_END
#define CC_PACKED __attribute__((packed))
#define CC_ALIGNED(n) __attribute__((aligned (n)))
#ifdef __rtk__
#include <kern/assert.h>
#define CC_ASSERT(exp) ASSERT (exp)
#else
#define CC_ASSERT(exp) assert (exp)
@ -53,11 +56,11 @@ extern "C"
#define CC_ATOMIC_OR(var,val) __atomic_or_fetch(&var,val,__ATOMIC_SEQ_CST)
#if BYTE_ORDER == BIG_ENDIAN
#define htoes(x) CC_SWAP16 (x)
#define htoel(x) CC_SWAP32 (x)
#define htoes(x) CC_SWAP16 ((uint16_t)(x))
#define htoel(x) CC_SWAP32 ((uint32_t)(x))
#else
#define htoes(x) (x)
#define htoel(x) (x)
#define htoes(x) ((uint16_t)(x))
#define htoel(x) ((uint32_t)(x))
#endif
#define etohs(x) htoes (x)
@ -71,7 +74,7 @@ extern "C"
#ifdef ESC_DEBUG
#ifdef __rtk__
#include <rprint.h>
#include <kern/rprint.h>
#define DPRINT(...) rprintp ("soes: "__VA_ARGS__)
#else
#include <stdio.h>