--- a/Makefile.in Mon Jun 04 17:59:50 2007 +0200
+++ b/Makefile.in Tue Jun 05 16:41:38 2007 +0200
@@ -30,6 +30,13 @@
echo Doxygen generation!!
doxygen doc/doxygen/Doxyfile
+manual:
+ cd doc/manual/en && \
+ pdflatex manual.tex && \
+ pdflatex manual.tex && \
+ rm manual.aux manual.log manual.out manual.toc && \
+ xpdf manual.pdf
+
objdictgen:
$(MAKE) -C objdictgen all
--- a/doc/doxygen/Doxyfile Mon Jun 04 17:59:50 2007 +0200
+++ b/doc/doxygen/Doxyfile Tue Jun 05 16:41:38 2007 +0200
@@ -5,7 +5,7 @@
#---------------------------------------------------------------------------
PROJECT_NAME = CanFestival
PROJECT_NUMBER = 3
-OUTPUT_DIRECTORY =
+OUTPUT_DIRECTORY = ./doc/doxygen
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
@@ -72,7 +72,7 @@
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
-INPUT = /home/epimerde/documents/tc11/CanFestival-3/src
+INPUT = ./src
FILE_PATTERNS = *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py *.C *.CC *.C++ *.II *.I++ *.H *.HH *.H++ *.CS *.PHP *.PHP3 *.M *.MM *.PY
RECURSIVE = YES
EXCLUDE =
@@ -88,14 +88,14 @@
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
-SOURCE_BROWSER = NO
+SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
-REFERENCED_BY_RELATION = NO
-REFERENCES_RELATION = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
-VERBATIM_HEADERS = NO
+VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
@@ -195,9 +195,9 @@
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-CLASS_DIAGRAMS = YES
+CLASS_DIAGRAMS = NO
HIDE_UNDOC_RELATIONS = YES
-HAVE_DOT = NO
+HAVE_DOT = YES
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
Binary file doc/manual/en/Pictures/100000000000006D000000A31EC8CB54.png has changed
Binary file doc/manual/en/Pictures/10000000000000AA0000006014F74635.png has changed
Binary file doc/manual/en/Pictures/10000000000000AB000000C88F594413.png has changed
Binary file doc/manual/en/Pictures/10000000000000AC000000C9C3F53FA6.png has changed
Binary file doc/manual/en/Pictures/10000000000000B6000000DF1EDD1E73.png has changed
Binary file doc/manual/en/Pictures/100000000000022C000000DEDAD2140C.png has changed
Binary file doc/manual/en/Pictures/1000000000000396000000FFC42573DA.png has changed
Binary file doc/manual/en/Pictures/10000201000000B7000000C66AF89CD5.png has changed
Binary file doc/manual/en/Pictures/10000201000001010000011DA724D25C.png has changed
Binary file doc/manual/en/Pictures/100002010000013A0000004A96B0C1FF.png has changed
Binary file doc/manual/en/Pictures/10000201000001C4000000DD129D4661.png has changed
Binary file doc/manual/en/Pictures/10000201000001C40000010766961D7F.png has changed
Binary file doc/manual/en/Pictures/10000201000001CB0000015F4FC09B68.png has changed
Binary file doc/manual/en/Pictures/10000201000001FC000001E5D65E8766.png has changed
Binary file doc/manual/en/Pictures/1000020100000258000000832C6FFAB4.png has changed
Binary file doc/manual/en/Pictures/10000201000002DE000001D82D89C224.png has changed
Binary file doc/manual/en/Pictures/10000201000002F30000020B23ED7F67.png has changed
Binary file doc/manual/en/Pictures/10000201000003440000025ACC3FD2F1.png has changed
Binary file doc/manual/en/Pictures/10000201000003CA0000016604E6A5EF.png has changed
Binary file doc/manual/en/Pictures/10000201000003E7000001C7B0296577.png has changed
Binary file doc/manual/en/Pictures/10000201000003F9000002CF880931E7.png has changed
Binary file doc/manual/en/Pictures/10000201000003F9000002CF8B0CDAEA.png has changed
Binary file doc/manual/en/manual.pdf has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/manual/en/manual.tex Tue Jun 05 16:41:38 2007 +0200
@@ -0,0 +1,1831 @@
+\documentclass[12pt,twoside]{article}
+\usepackage[ascii]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[french,english]{babel}
+\usepackage{amsmath,amssymb,amsfonts,textcomp}
+\usepackage{color}
+\usepackage{calc}
+\usepackage{longtable}
+\usepackage{hyperref}
+\usepackage{graphics}
+\usepackage{graphicx}
+\DeclareGraphicsExtensions{.jpg}
+\DeclareGraphicsExtensions{.png}
+\hypersetup{colorlinks=true, linkcolor=blue, filecolor=blue, pagecolor=blue, urlcolor=blue}
+
+\newenvironment{changemargin}[2]{\begin{list}{}{%
+\setlength{\topsep}{0pt}%
+\setlength{\leftmargin}{0pt}%
+\setlength{\rightmargin}{0pt}%
+\setlength{\listparindent}{\parindent}%
+\setlength{\itemindent}{\parindent}%
+\setlength{\parsep}{0pt plus 1pt}%
+\addtolength{\leftmargin}{#1}%
+\addtolength{\rightmargin}{#2}%
+}\item }{\end{list}}
+
+
+%%%%\%%%%%%%% titre, auteurs, date, etc...%%%%%%%%%%%%%%%%%%
+
+\title{\Huge Documentation}
+\author{Edouard TISSERANT}
+\date{\today}
+
+% Text styles
+\newcommand\textstyleTeletype[1]{\texttt{#1}}
+% Outline numbering
+\setcounter{secnumdepth}{5}
+\renewcommand\thesection{\arabic{section} -}
+\renewcommand\thesubsection{\arabic{section}.\arabic{subsection})}
+\renewcommand\thesubsubsection{\arabic{section}.\arabic{subsection}.\arabic{subsubsection})}
+\renewcommand\theparagraph{\alph{paragraph})}
+\renewcommand\thesubparagraph{\roman{subparagraph})}
+% List styles
+\newcommand\liststyleLi{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLii{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLiii{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLiv{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLv{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLvi{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLvii{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLviii{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLix{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLx{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLxi{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLxii{%
+\renewcommand\labelitemi{{--}}
+\renewcommand\labelitemii{{--}}
+\renewcommand\labelitemiii{{--}}
+\renewcommand\labelitemiv{{--}}
+}
+\newcommand\liststyleLxiii{%
+\renewcommand\labelitemi{{\textbullet}}
+\renewcommand\labelitemii{{\textbullet}}
+\renewcommand\labelitemiii{{\textbullet}}
+\renewcommand\labelitemiv{{\textbullet}}
+}
+% Pages styles (master pages)
+\makeatletter
+\newcommand\ps@Standard{%
+\renewcommand\@oddhead{}%
+\renewcommand\@evenhead{}%
+\renewcommand\@oddfoot{}%
+\renewcommand\@evenfoot{\@oddfoot}%
+\setlength\paperwidth{8.2673in}\setlength\paperheight{11.6925in}\setlength\voffset{-1in}\setlength\hoffset{-1in}\setlength\topmargin{0.1965in}\setlength\headheight{12pt}\setlength\headsep{0cm}\setlength\footskip{12pt+0.1965in}\setlength\textheight{11.6925in-0.1965in-0.7874in-0cm-12pt-0.1965in-12pt}\setlength\oddsidemargin{0.3937in}\setlength\textwidth{8.2673in-0.3937in-0.3937in}
+\renewcommand\thepage{\arabic{page}}
+\setlength{\skip\footins}{0.0398in}\renewcommand\footnoterule{\vspace*{-0.0071in}\noindent\textcolor{black}{\rule{0.25\columnwidth}{0.0071in}}\vspace*{0.0398in}}
+}
+\makeatother
+\pagestyle{Standard}
+\setlength\tabcolsep{1mm}
+\renewcommand\arraystretch{1.3}
+\begin{document}
+{\centering\sffamily
+CanFestival3. Version 3.0\newline
+The CANOpen stack manual
+\par}
+
+\setcounter{tocdepth}{2}
+\renewcommand\contentsname{Table of contents}
+\tableofcontents
+\section{Introduction}
+This document describe the CANOpen layer.CanFestival is an OpenSource
+(LGPL) CANOpen framework.
+
+\subsection{The CanFestival project}
+This project, initiated by Edouard TISSERANT in 2001, as grown thanks to
+Francis DUPIN and other contributors.
+
+Today, CanFestival focuses on providing an ANSI{}-C platform independent
+CANOpen stack that can be implemented as master or slave nodes on PCs,
+Real{}-time IPCs, and Microcontrollers.
+
+CanFestival is a project supported by Lolitech.
+
+\subsection{What is CANopen}
+CANopen is a CAN based high level protocol. It defines some protocols to
+:
+
+\liststyleLi
+\begin{enumerate}
+\item Configure a CAN network.
+\item Transmit data to a specific node or in broadcast.
+\item Administrate the network. For example detecting a not responding
+node.
+\end{enumerate}
+The documentation can be found in the Can in automation website :
+
+\href{http://www.can-cia.de/canopen}{http://www.can{}-cia.de/canopen}
+
+The most important document about CANopen is the normative CiA Draft
+Standard 301, version 4.02. You can now download with no cost the
+specification in Can in automation website.
+
+To continue reading this document, let us assume that you have read some
+papers introducing CANopen.
+
+\section{CanFestival Features}
+\subsection{Tools }
+The CANopen library is coming with some tools :
+
+\liststyleLii
+\begin{enumerate}
+\item Object Dictionary editor GUI. WxPython Model{}-View{}-Controler
+based GUI, that help a lot in generating object dictionary source code
+for each node.
+\item A configure script, that let you chose compile time options such
+as target CPU/HOST, CAN and TIMER drivers.\newline
+This script have not been generated with autoconf, it have been made
+keeping micro{}-controller target in mind.
+\end{enumerate}
+\subsection{Standard conformance}
+\paragraph{Multi{}-Platform}
+\liststyleLiii
+\begin{enumerate}
+\item Library source code is C{}-ANSI.
+\item Driver and examples coding conventions merely depend on target
+specific contributor/compiler.
+\item Unix compatible interfaces and examples should compile and run on
+any Unix system (tested on GNU/Linux and GNU/FreeBSD).
+\end{enumerate}
+\paragraph{CanOpen conformance}
+{\bfseries\upshape
+DS{}-301}
+
+\liststyleLiv
+\begin{enumerate}
+\item Should conform to DS301. V.4.02 13 february 2002.
+\item Master and Slave functionality implemented.
+\item Sending SYNC implemented.
+\item 1 SDO server per node. (update: more than one possible. To be more
+tested)
+\item Unlimited SDO client.
+\item SDO transmission mode : normal, expedited download and upload.
+\item Unlimited PDO receive.
+\item Unlimited PDO transmit.
+\item Object Data type implemented : 8, 16, 32 bits values, and fixed
+length strings.
+\item Slave state full implemented.
+\item NMT to change slave{\textquotesingle}s state implemented.
+\item PDO transmission mode : on request, every reception of 0 to n
+SYNC, on event.
+\item NMT Heartbeat implemented : A node can be either heartbeat
+producer or receiver.
+\item NMT NodeGuard implemented : Not fully implemented.
+\item TIME (time Stamp) : Not implemented.
+\item EMCY (emergency objects) : Not implemented.
+\item PDO Mapping bit per bit implemented.
+\end{enumerate}
+{\bfseries\upshape
+DS{}-302}
+
+\liststyleLiv
+\begin{enumerate}
+\item Concise \ DFC : implemented.
+\end{enumerate}
+\section{How to start}
+\subsection{Host requirements}
+What you need on your development workstation.
+
+\subsubsection{Object Dictionary Editor GUI}
+\liststyleLv
+\begin{enumerate}
+\item Python, with
+\item wxPyhon modules installed (at least version 2.6.3).
+\item Gnosis xml tools. (Optional can also be installed locally to the
+project automatically will the help of a Makefile. Please see
+\hyperlink{a91UsingDictionaryEditorGUIoutline}{9.1) Using Dictionary
+Editor GUI} )
+\end{enumerate}
+\subsubsection[\ Linux and Unix{}-likes]{\ Linux and Unix{}-likes}
+\liststyleLv
+\begin{enumerate}
+\item Linux, FreeBSD, Cygwin or any Unix environment with GNU toolchain.
+\item The GNU C compiler (gcc) or any other ANSI{}-C compiler for your
+target platform.
+\item Xpdf, and the official 301\_v04000201.pdf file in order to get GUI
+context sensitive help. Download the ds301 at
+\href{http://www.can-cia.org/downloads/ciaspecifications/?1390}{http://www.can{}-cia.org/downloads/ciaspecifications/?1390}.
+\item GNU Make
+\item Bash and sed
+\end{enumerate}
+\subsubsection{Windows (for native win32 target)}
+\liststyleLv
+\begin{enumerate}
+\item Visual Studio Express 2005 or worst.
+\item Microsoft platform SDK (requires Genuine Advantage)
+\item Cygwin (for configuration only)
+\end{enumerate}
+\subsection{How to get CanFestival}
+Please always use CVS, this is the best way to get the most reactive
+support from the developer community :
+
+cvs {}-d:pserver:anonymous@lolitech.dyndns.org:/canfestival
+login\newline
+(type return, without entering a password)
+
+Then, enter : \newline
+cvs {}-z3 {}-d:pserver:anonymous@lolitech.dyndns.org:/canfestival co
+{}-P CanFestival{}-3
+
+\section{Understanding Canfestival}
+\subsection{CanFestival Project tree layout}
+Simplified directory structure.
+
+{\ttfamily\bfseries
+./src ANSI{}-C source of CANOpen stack}
+
+{\ttfamily\bfseries
+\ /include Exportables Header files}
+
+{\ttfamily\bfseries
+./drivers Interfaces to specific platforms/HW}
+
+{\ttfamily
+./drivers/unix Linux and Cygwin OS interface}
+
+{\ttfamily
+./drivers/win32 Native Win32 OS interface}
+
+{\ttfamily
+./drivers/timers\_xeno Xenomai timers/threads (Linux only)}
+
+{\ttfamily
+./drivers/timers\_unix Posix timers/threads (Linux, Cygwin)}
+
+{\ttfamily
+./drivers/can\_peak\_linux PeakSystem CAN library interface}
+
+{\ttfamily
+./drivers/can\_peak\_win32 PeakSystem PCAN{}-Light interface}
+
+{\ttfamily
+./drivers/can\_uvccm\_win32 Acacetus{\textquotesingle}s RS232
+``CAN{}-uVCCM'' interface}
+
+{\ttfamily
+./drivers/can\_virtual Fake CAN network (Linux, Cygwin)}
+
+{\ttfamily
+./drivers/hcs12 HCS12 full target interface}
+
+{\ttfamily\bfseries
+./examples Examples}
+
+{\ttfamily
+./examples/TestMasterSlave 2 nodes, NMT SYNC SDO PDO, win32+unix}
+
+{\ttfamily
+./examples/TestMasterMicroMod 1 node, control Peak I/O Module, unix}
+
+{\ttfamily
+./examples/gene\_SYNC\_HCS12 Just send periodic SYNC on HCS12}
+
+{\ttfamily
+./examples/win32test Ask some DS301 infos to a node (\textbf{win32)}}
+
+{\ttfamily\bfseries
+./objdictgen Object Dictionary editor GUI}
+
+{\ttfamily
+./objdictgen/config Pre{}-defined OD profiles}
+
+{\ttfamily
+./objdictgen/examples Some examples/test OD}
+
+{\ttfamily\bfseries
+./doc Project and CanOpen doc}
+
+\subsection{Implement CanFestival in your application}
+
+ \begin{center}
+ \includegraphics[width=20cm]{Pictures/10000201000003F9000002CF880931E7.png}
+\end{center}
+
+\bigskip
+
+\subsection{CanFestival CAN interfaces}
+Because most CAN controllers and drivers implement FIFOs, CanFestival
+consider sending message as a non bloking operation.
+
+In order to prevent reentrent calls to the stack, messages reception is
+implemented differently on {\textmu}C and OS.:
+
+\liststyleLvi
+\begin{enumerate}
+\item {\textmu}C must provide interuption masking for timer and can
+receive IT\newline
+ \begin{center}
+ \includegraphics[width=20cm]{Pictures/10000201000003CA0000016604E6A5EF.png}
+\end{center}
+\item OS must provide a receive thread, a timer thread and a mutex. CAN
+reception is a bloking operation.\newline
+\begin{center}
+ \includegraphics[width=20cm]{Pictures/10000201000003F9000002CF8B0CDAEA.png}
+\end{center}
+\end{enumerate}
+\subsection{CanFestival events scheduling}
+A CanOpen node must be able to take delayed actions.
+
+As exemples, periodic sync emission, heartbeat production or SDO timeout
+need to set some alarms that will be called later and do the job.
+
+{\textmu}C generaly do not have enough free timers to handle all the
+CanOpen needs directly. Moreover, CanFestival internal data may be
+corrupt by reentrant calls.
+
+CanFestival implement a micro{}-scheduler (timer.c). It uses only one
+timer to mimic many timers. It manage an alarm table, and call alarms
+at desired time.
+
+\begin{center}
+ \includegraphics[width=20cm]{Pictures/100000000000022C000000DEDAD2140C.png}
+\end{center}
+
+Scheduler can handle short clock value ranges limitation found on some
+{\textmu}C. As an example, value range for a 16bit clock counter with
+4{\textmu}s tick is crossed within 0.26 seconds... Long alarms must be
+segmented.
+
+Chronogram illustrate a long alarm (A) and a short periodic alarm (B),
+with a A value {\textgreater} clock range {\textgreater} B value.
+Values t0...t8 are successive setTimer call parameter values. t1
+illustrates an intermediate call to TimeDispatch, caused by a delay
+longer than clock range. Because of long alarm segmentation, at the end
+of t1, TimeDispatch call will not trig any alarm callback.
+
+\begin{center}
+ \includegraphics[width=20cm]{Pictures/1000000000000396000000FFC42573DA.png}
+\end{center}
+
+\section{Linux Target}
+Linux target is default configure target.
+
+\subsection{Linux Compilation and installation}
+Call ./configure {--}help to see all available compile time options.
+
+After invoking ./configure with your platform specific switches, just
+type make.
+
+{\ttfamily
+./configure [options]}
+
+{\ttfamily
+make}
+
+{\ttfamily
+\textstyleTeletype{make install}}
+
+\subsubsection{Standard Linux node}
+Configure switch:
+
+{\ttfamily
+ {}-{}-timers=unix}
+
+To do a CANopen node running on PC{}-Linux, you need :
+
+\liststyleLvii
+\begin{enumerate}
+\item A working linux distribution
+\item One or more Peak system PC CAN interface and the last Peak Linux
+driver installed.
+\end{enumerate}
+\subsubsection{Real{}-Time Linux node}
+Configure switch:
+
+{\ttfamily
+ {}-{}-timers=xeno}
+
+To do a CANopen node running on PC{}-Linux, you need :
+
+\liststyleLviii
+\begin{enumerate}
+\item A working Linux distribution patched with XENOMAI 2.1 or greater.
+\item One or more Peak system PC CAN interface and the last Peak Real
+Time Linux driver installed.
+\end{enumerate}
+\subsubsection{CAN devices}
+Curently supported CAN devices and corresponding configure switch:
+
+\paragraph{Peak systems}
+Configure switch:
+
+{\ttfamily
+{}-{}-can=peak\_linux}
+
+PeakSystems CAN interface is automatically chosen as default CAN
+interface if libpcan is present in the system.
+
+Please download driver at
+\href{http://www.peak-system.com/linux}{http://www.peak{}-system.com/linux}
+and follow instructions in order to install driver on your system.
+
+\paragraph{Socket{}-Can (http://socketcan.berlios.de)}
+Configure switch:
+
+{\ttfamily
+{}-{}-can=socket}
+
+\paragraph{LinCan}
+Configure switch:
+
+{\ttfamily
+{}-{}-can=lincan}
+
+\paragraph{Virtual CAN interfaces (for test/debug)}
+Configure switch:
+
+{\ttfamily
+{}-{}-can=virtual}
+
+Virtual CAN interface use Unix pipes to emulate a virtual CAN network.
+Each message issued from a node is repeat to all other nodes. Currently
+only works with nodes running in the same process, and does not support
+work with Xenomai.
+
+\subsection{Testing your CanFestival installation}
+Sample provided in /example/TestMasterSlave is installed into your
+system during installation.
+
+{\ttfamily
+TestMasterSlave}
+
+Default can driver library is libcanfestival\_can\_virtual.so., which
+will simply pass CAN messages through Unix pipes between Master and
+Slave.
+
+You may also want to specify different can interface and define some CAN
+ports. An other example using Peak{\textquotesingle}s dual PCMCIA
+(configure and install with {--}can=peak) :
+
+{\ttfamily
+TestMasterSlave {}-l libcanfestival\_can\_peak.so {}-s 40 {}-m 41}
+
+\section{Windows Targets}
+CanFestival can be compiled and run on Windows platform. It is possible
+to use both Cygwin and win32 native runtime environment.
+
+\subsection{Object Dictionary Editor GUI installation.}
+Please refer to
+\hyperlink{a821UsingDictionaryEditorGUIoutline}{8.2.1)Using Dictionary
+Editor GUI}
+
+\subsection{CYGWIN}
+\subsubsection{Requirements}
+Cygwin have to be installed with those packages :
+
+\liststyleLix
+\begin{enumerate}
+\item gcc
+\item unzip
+\item wget
+\item make
+\end{enumerate}
+Currently, the only supported CAN devices are PeakSystems ones, with
+PcanLight driver and library.
+
+Please download driver at
+\href{http://www.peak-system.com/themen/download_gb.html}{http://www.peak{}-system.com/themen/download\_gb.html}
+\ and follow instructions in order to install driver on your system.
+
+Install Cygwin as required, and the driver for your Peak CAN device.
+
+Open a Cygwin terminal, and follow those instructions:
+
+\subsubsection{Cygwin configuration and compilation}
+\paragraph{A single node with PcanLight and Peak CAN{}-USB adapter}
+Download the PCAN{}-Light Zip file for your HW ( URL from download page
+):
+
+{\ttfamily
+wget http://www.peak{}-system.com/files/usb.zip}
+
+Extract its content into your cygwin home (it will create a ``Disk''
+directory):
+
+{\ttfamily
+unzip usb.zip}
+
+Configure CanFestival3 providing path to the desired PcanLight
+implementation:
+
+{\ttfamily
+cd CanFestival{}-3}
+
+{\ttfamily
+export PCAN\_INCLUDE=\~{}/Disk/PCAN{}-Light/Api/}
+
+{\ttfamily
+export PCAN\_HEADER=Pcan\_usb.h}
+
+{\ttfamily
+export PCAN\_LIB=\~{}/Disk/PCAN{}-Light/Lib/Visual{\textbackslash}
+C++/Pcan\_usb.lib}
+
+{\ttfamily
+./configure {}-{--}can=peak\_win32}
+
+{\ttfamily
+make}
+
+In order to test, you have to use another CanFestival node, connect with
+a CAN cable.
+
+{\ttfamily
+cp \~{}/Disk/PCAN{}-Light/Pcan\_usb.dll .}
+
+{\ttfamily
+./examples/TestMasterSlave/TestMasterSlave {\textbackslash}}
+
+{\ttfamily
+ {}-l drivers/can\_peak\_win32/cygcan\_peak\_win32.dll
+{\textbackslash}}
+
+{\ttfamily
+ {}-S 500K {}-M none}
+
+Then, on the other node :
+
+{\ttfamily
+./TestMasterSlave {}-l my\_driver.so {}-S none {}-M 500K}
+
+Now messages are beeing exchanged between master and slave node.
+
+\paragraph{Two nodes with PcanLight and Peak dual PCMCIA{}-CAN adapter}
+Download the PCAN{}-Light Zip file for your HW ( URL from download page
+):
+
+{\ttfamily
+wget http://www.peak{}-system.com/files/pccard.zip}
+
+Extract its content into your cygwin home (it will create a ``Disk''
+directory):
+
+{\ttfamily
+unzip pccard.zip}
+
+The configure CanFestival3 providing path to the desired PcanLight
+implementation:
+
+{\ttfamily
+export PCAN\_INCLUDE=\~{}/Disk/PCAN{}-Light/Api/\newline
+export PCAN\_HEADER=Pcan\_pcc.h\newline
+export PCAN\_LIB=\~{}/Disk/PCAN{}-Light/Lib/Visual{\textbackslash}
+C++/Pcan\_pcc.lib\newline
+export PCAN2\_HEADER=Pcan\_2pcc.\newline
+export PCAN2\_LIB=\~{}/Disk/PCAN{}-Light/Lib/Visual{\textbackslash}
+C++/Pcan\_2pcc.lib}
+
+In order to test, just connect together both CAN ports of the PCMCIA
+card. Don{\textquotesingle}t forget 120ohms terminator.
+
+{\ttfamily
+cp \~{}/Disk/PCAN{}-Light/Pcan\_pcc.dll .}
+
+{\ttfamily
+cp \~{}/Disk/PCAN{}-Light/Pcan\_2pcc.dll .}
+
+{\ttfamily
+./examples/TestMasterSlave/TestMasterSlave {\textbackslash}}
+
+{\ttfamily
+ {}-l drivers/can\_peak\_win32/cygcan\_peak\_win32.dll}
+
+Messages are then exchanged between master and slave node, both inside
+TestMasterSlave{\textquotesingle}s process.
+
+\subsection{Visual Studio C++}
+\subsubsection{Requirements}
+Minimal Cygwin installation is required at configuration time in order
+to create specific header files (config.h and cancfg.h). Once this
+files created, cygwin is not necessary any more.
+
+Project and solution files have been created and tested with Visual
+Studio Express 2005. Be sure to have installed Microsoft Platform SDK,
+as recommended at the end of Visual Studio installation.
+
+\subsubsection{Configuration with cygwin}
+Follow instructions given at
+\hyperlink{a422Cygwinconfigurationandcompilationoutline}{4.2.2)Cygwin
+configuration and compilation}, but do neither call make nor do tests,
+just do configuration steps. This will create headers files accordingly
+to your configuration parameters, and the desired CAN hardware.
+
+\subsubsection{Compilation with Visual Studio}
+You can either load independents ``*.vcproj'' project files along your
+own projects in your own solution or load the provided
+``CanFestival{}-3.vc8.sln'' solution files directly.
+
+Build CanFestival{}-3 project first.
+
+\paragraph{PcanLight and the can\_peak\_win32 project.}
+Chosen Pcan\_xxx.lib and eventually Pcan\_2xxx.lib files must be added
+to can\_peak\_win32 \ \ project before build of the DLL.
+
+\subsubsection{Testing}
+Copy eventually needed dlls (ie : Pcan\_Nxxx.lib) into Release or Debug
+directory, and run the test program:
+
+{\ttfamily
+TestMasterSlave.exe {}-l can\_peak\_win32.dll}
+
+\section{Motorola HCS12}
+The examples have been tested on a MC9S12DG255 mounted on a
+Elektronikladen HCS12 T{}-board.
+
+Beware that there are a few differences in the MSCAN module of the
+68HC12 and HCS12 microcontroller. For a HC12, you must adapt the driver
+that we provide for \ the HCS12.
+
+For the difference MSCAN HC12/HCS12, see the Motorola application note
+AN2011/D.
+
+Configure switch:
+
+{\ttfamily
+ {}-{}-target=hcs12}
+
+To do a CANopen node running on a microncontroller Motorola MC9S12DP256,
+you need :
+
+\liststyleLx
+\begin{enumerate}
+\item The compiler GNU gcc for HC11, HC12, HCS12 : m6811{}-elf. \newline
+Download the \textbf{release 3.1} at :
+\ \href{http://m68hc11.serveftp.org/m68hc11_pkg_rpm.php}{http://m68hc11.serveftp.org/m68hc11\_pkg\_rpm.php}
+
+\item A board with this chip. We are using the T{}-board from
+Electronikladden.
+\item At least about 40 kBytes of program memory.
+\item A tool to flash the memory. (We are using the hight cost
+Lauterbach debugger).
+\end{enumerate}
+\subsection{Running a HCS12 node}
+\subsubsection{Compiling Canfestival:}
+{\ttfamily
+./configure {--}target=hcs12}
+
+\subsubsection{Compiling and building an example}
+Enter in the folder of an HCS12 example,
+
+{\ttfamily
+make all}
+
+\subsubsection{Flashing the memory :}
+Use your prefered loader ! If you are using a debugger Lauterbach, you
+can load the bash file : trace32\_flash\_programmer.cmm. It loads
+directly the elf file.
+
+\subsubsection{Connecting to a serial RS232 console :}
+Connect the portS(TxD0) of the HCS12 to a console configured at 19200
+bauds 8N1, via a Max232 chip to adapt the electricals levels. On Linux,
+you can use minicom. Connecting to a console is usefull to read the
+messages, but not required.
+
+\subsubsection{Connecting to the CAN network :}
+Connect the port CAN0 (pin PM0, PM1) to the network via a CAN
+controller. On our board, the CAN controler is a PCA82C250 chip.
+
+\subsubsection{starting the node :}
+Press the reset of your HCS12 board.
+
+\section{Example and test program:}
+The ``examples'' directory contains some test program you can use as
+example for your own developments.
+
+\subsection{TestMasterSlave}
+{\ttfamily
+**************************************************************}
+
+{\ttfamily
+* \ TestMasterSlave
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ A simple example for PC. It does implement 2 CanOpen \ \ \ \ \ *}
+
+{\ttfamily
+* \ nodes in the same process. A master and a slave. Both \ \ \ \ *}
+
+{\ttfamily
+* \ communicate together, exchanging periodically NMT, SYNC, \ *}
+
+{\ttfamily
+* \ SDO and PDO. Master configure heartbeat producer time \ \ \ \ *}
+
+{\ttfamily
+* \ at 1000 ms for slave node{}-id 0x02 by concise DCF.
+\ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ Usage:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ ./TestMasterSlave \ [OPTIONS]
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ OPTIONS:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-l : Can library
+[{\textquotedbl}libcanfestival\_can\_virtual.so{\textquotedbl}]
+\ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ Slave:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-s : bus name [{\textquotedbl}0{\textquotedbl}]
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-S : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable) \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ Master:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-m : bus name [{\textquotedbl}1{\textquotedbl}]
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-M : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable) \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+**************************************************************}
+
+
+\bigskip
+
+{\sffamily
+Notes for Concise DCF :}
+
+
+\bigskip
+
+{\sffamily
+ In this example, Master configure \ heartbeat producer time at 1000 ms
+for slave node{}-id 0x02 by concise DCF according DS{}-302 profile. }
+
+{\sffamily
+ }
+
+{\sffamily
+ Index 0x1F22 , sub{}-index 0x00 of the master OD, correspond to the
+number of entries. This equal to the maximum possible nodeId (127).
+Each sub{}-index points to the Node{}-ID of the device, to which the
+configuration belongs. }
+
+
+\bigskip
+
+{\sffamily
+ To add more parameters configurations to the slave, the value at
+sub{}-index 0x02 must be a binary stream (little{}-endian) following
+this structure :}
+
+{\sffamily
+ }
+
+{\sffamily
+[ nb of entries / index parameter 1 / sub{}-index parameter 1 \ / size
+data parameter 1 \ / data parameter 1 / index parameter n / ...]}
+
+{\sffamily
+\ \ \ \ \ \ (UNS32) \ \ \ \ \ \ \ \ \ \ \ \ (UNS16) (UNS8)
+\ \ \ \ \ \ \ \ \ \ \ (UNS32) \ \ \ (DOMAIN)}
+
+{\sffamily
+ }
+
+{\sffamily
+ So the binary value stream to configure heartbeat producer time must be
+: }
+
+
+\bigskip
+
+{\sffamily
+ 0100000017100002000000e803}
+
+
+\bigskip
+
+{\sffamily
+The slave node is configured just before the Master entering in
+Pre\_operational state.}
+
+\subsection{gene\_SYNC\_HCS12 :}
+This is a simple CanOpen node that only send cyclic SYNC message. It
+demonstrate implementation on HCS12 based board.
+
+
+\bigskip
+
+\subsection{TestMasterMicroMod }
+{\ttfamily
+**************************************************************}
+
+{\ttfamily
+* \ TestMasterMicroMod
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ A simple example for PC.
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ A CanOpen master that control a MicroMod module:
+\ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- setup module TPDO 1 transmit type
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- setup module RPDO 1 transmit type
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- setup module hearbeatbeat period
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- disable others TPDOs
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- set state to operational
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- send periodic SYNC
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- send periodic RPDO 1 to Micromod (digital output) \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- listen Micromod{\textquotesingle}s TPDO 1 (digital input)
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ {}- Mapping RPDO 1 bit per bit (digital input)
+\ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ Usage:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ ./TestMasterMicroMod \ [OPTIONS]
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ OPTIONS:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-l : Can library
+[{\textquotedbl}libcanfestival\_can\_virtual.so{\textquotedbl}]
+\ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ Slave:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-i : Slave Node id format [0x01 , 0x7F]
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ Master:
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-m : bus name [{\textquotedbl}1{\textquotedbl}]
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+* \ \ \ \ {}-M : 1M,500K,250K,125K,100K,50K,20K,10K
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+*
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ *}
+
+{\ttfamily
+**************************************************************}
+
+\section{Developing a new node}
+Using provided examples as a base for your new node is generally a good
+idea. You can also use the provided *.od files as a base for your node
+object dictionary.
+
+Creating a new CanOpen node implies to define the Object Dictionary of
+this node. For that, developer have to provide a C file. This C file
+contains the definition of all dictionary entries, and some kind of
+index table that helps the stack to access some entries directly.
+
+\subsection{Using Dictionary Editor GUI}
+The Object Dictionary Editor is a WxPython based GUI that is used to
+create the C file needed to create a new CanOpen node.
+
+\subsubsection{Installation and usage on Linux}
+You first have to download and install Gnosis XML modules. This is
+automated by a Makefile rule.
+
+{\ttfamily
+cd objdictgen}
+
+{\ttfamily
+make}
+
+Now start the editor.
+
+{\ttfamily
+python objdictedit.py [od files...]}
+
+\subsubsection{Installation and usage on Windows}
+Install Python (at least version 2.4) and wxPython (at least version
+2.6.3.2).
+
+Cygwin users can install Gnosis XML utils the same as Linux use. Just
+call make.
+
+{\ttfamily
+cd objdictgen}
+
+{\ttfamily
+make}
+
+Others will have to download and intall Gnosis XML by hand :
+
+{\ttfamily
+Gnosis Utils:}
+
+{\ttfamily
+http://freshmeat.net/projects/gnosisxml/}
+
+{\ttfamily
+http://www.gnosis.cx/download/Gnosis\_Utils.More/Gnosis\_Utils{}-1.2.1.win32{}-py24.exe}
+
+{\ttfamily
+Get latest version.}
+
+Download CanFestival archive and uncompress it. Use windows file
+explorer to go into CanFestival3{\textbackslash}objdicgten, and
+double{}-click on objdictedit.py.
+
+\subsubsection{About}
+The Object Dictionary editor GUI is a python application that use the
+Model{}-View{}-Controller design pattern. It depends on WxPython to
+display view on any supported platform.
+
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/10000201000001FC000001E5D65E8766.png}
+\end{center}
+
+\subsubsection{Main view}
+Top list let you choose dictionary section, bottom left list is the
+selected index in that dictionary, and bottom right list are edited
+sub{}-indexes.
+
+ \begin{center}
+ \includegraphics[width=5cm]{Pictures/10000201000001FC000001E5D65E8766.png}
+\end{center}
+
+ \begin{center}
+ \includegraphics[width=5cm]{Pictures/10000000000000B6000000DF1EDD1E73.png}
+\end{center}
+ \begin{center}
+ \includegraphics[width=5cm]{Pictures/10000000000000AC000000C9C3F53FA6.png}
+\end{center}
+ \begin{center}
+ \includegraphics[width=5cm]{Pictures/100000000000006D000000A31EC8CB54.png}
+\end{center}
+ \begin{center}
+ \includegraphics[width=5cm]{Pictures/10000000000000AA0000006014F74635.png}
+\end{center}
+
+\subsubsection{New node}
+Edit your node name, ID and type. Choose your inherited specific
+profile.
+
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/10000201000001CB0000015F4FC09B68.png}
+\end{center}
+
+\subsubsection{Node info}
+Edit your node name, ID and type.
+
+ \begin{center}
+ \includegraphics[width=10cm]{Pictures/10000201000001010000011DA724D25C.png}
+\end{center}
+
+\subsubsection{Profile editor}
+Chose the used profile to edit.\newline
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/10000000000000AB000000C88F594413.png}
+\end{center}
+
+Pick up optional chosen profile entries.\newline
+ \begin{center}
+ \includegraphics[width=10cm]{Pictures/10000201000002DE000001D82D89C224.png}
+\end{center}
+
+\subsubsection{User types}
+Use User Types to implement value boundaries, and string lentgth\newline
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/10000201000001C40000010766961D7F.png}
+\end{center}
+
+\subsubsection{Mapped variable}
+Add your own specific dictionary entries and associated mapped
+variables.\newline
+ \begin{center}
+ \includegraphics[width=10cm]{Pictures/10000201000001C4000000DD129D4661.png}
+\end{center}
+
+\subsubsection{Integrated help}
+Using F1 key, you can get context sensitive help.\newline
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/10000201000002F30000020B23ED7F67.png}
+\end{center}
+
+In order to do that, official 301\_v04000201.pdf file must be placed
+into doc/ directory, and xpdf must be present on your system.
+
+F2 key open HTML CanFestival help.\newline
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/10000201000003440000025ACC3FD2F1.png}
+\end{center}
+
+\subsection{Generating the object Dictionary}
+Once object dictionary has been edited and saved, you have to generate
+object dictionary C code for your CanFestival node.
+
+\subsubsection{With GUI}
+Menu entry ``File/Build Dictionary''.
+
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/10000201000000B7000000C66AF89CD5.png}
+\end{center}
+
+Choose C file to create or overwrite. Header file will be also created
+with the same prefix as C file.
+
+\subsubsection{With command line}
+{\ttfamily
+Usage of objdictgen.py :\newline
+python objdictgen.py XMLFilePath CfilePath}
+
+\section{FAQ}
+\subsection{General}
+\subsubsection{Does the code compiles on Windows ?}
+Yes, with both Cygwin and Visual Studio C++.
+
+Because CANopen layer is coded with C, put a compilation option /TC or
+/TP if you plan to mix C++ files. See the MSDN documentation about
+that.
+
+\subsubsection{How to fit the library to an other microcontr\^oler ?}
+First, be sure that you have at least 40K bytes of program memory, and
+about 2k of RAM.
+
+You have to create target specific interface to HW resources. Take model
+on bundled interfaces provided in drivers/ and create your own
+interface. You also have to update Makefile.in files for target
+specific cflags and options. Chose {--}targer= configure switch to
+compile your specific interface.
+
+You are welcome to contribute{}-back your own interfaces ! Other
+Canfestival users will use it and provide feedback, tests and
+enhancements.
+
+\subsubsection{Is CanFestival3 conform to DS301 v.4.02 ?}
+Thanks to Philippe Foureys (IUT of Valence), a slave node have been
+tested with the National Instrument CanOpen Conformance Test. It passed
+the test with success.
+
+Some very small unconformity have been found in very unusual situations,
+for example in the SDO code response to wrong messages.
+
+\subsection{LINUX}
+\subsubsection{How to use a Peaksystem CAN board ?}
+Just install peak driver and then compile and install Canfestival. Peak
+driver is detected at compile time.
+
+\subsubsection{How to use an unsupported CAN board ?}
+You have to install the specific driver on your system, with necessary
+libs and headers.
+
+Use can\_peak.c/h or can\_virtual.c/h as an example, and adapt it to
+your driver API.
+
+Execute configure script and choose {}-{}-can=mydriver
+
+\subsection{Win32}
+Compatibility:
+
+\liststyleLxi
+\begin{enumerate}
+\item Code was compiled MS VisualStudio 2003.NET and VisualStudio
+2005.NET for WindowsXP \ with ANSI and UNICODE configurations and for
+WindowsCE 5.0.
+\item Some preliminary testing was done, but not enough to be used in
+mission critical projects.
+\end{enumerate}
+Additional Features:
+
+\liststyleLxii
+\begin{enumerate}
+\item Non{}-integral integers support implementation UNS24, UNS40, UNS48
+etc.
+\item When enable debug output with DEBUG\_WAR\_CONSOLE\_ON or
+DEBUG\_ERR\_CONSOLE\_ON, you can navigate in CanFestival source code by
+double clicking at diagnostic lines in VisualStudio.NET 200X Debug
+Output Window.
+\end{enumerate}
+Custom size integral types such as INTEGER24, UNS40, INTEGER56 etc. have
+been defined as 64 bits integers. You will need to replace sizeof(TYPE)
+operators to sizeof\_TYPE definitions in generated code, i.e. replace
+sizeof(UNS40) with sizeof\_UNS40.
+
+
+\bigskip
+
+\subsection{HCS12}
+\subsubsection{Which board are you using ?}
+A T{}-board from elektronikladen with a MC9S12DP256 or MC9S12DG256.
+
+\subsubsection{Does the code compile with an other compiler than GNU gcc
+?}
+It is known to work with Metrowerks CodeWarrior. Here are some tips from
+Philippe Foureys. :
+
+\paragraph{Interrupt functions}
+\subparagraph{Code for GCC:}
+{\ttfamily
+ // prototype\newline
+ void \_\_attribute\_\_((interrupt))timer3Hdl(void):\newline
+ // function\newline
+ void \_\_attribute\_\_((interrupt))timer3Hdl(void)\{...\}}
+
+\subparagraph{Code for CodeWarrior}
+{\ttfamily
+ // protoype\newline
+ void interrupt timer3Hdl(void);\newline
+ // function\newline
+ pragma CODE\_SEG\_\_NEAR\_SEG\_NON\_BANKED\newline
+ void interrupt timer3Hdl(void)\newline
+ \{...\}\newline
+ pragma CODE\_SEG\_DEFAULT}
+
+\paragraph{Interrupt lock, unlock}
+\subparagraph{Code for GCC}
+{\ttfamily
+ void unlock (void)\newline
+ \{\newline
+ \ \_\_asm\_\_
+\_\_volatile\_\_({\textquotedbl}cli{\textquotedbl});\newline
+ \}\newline
+ void lock (void)\newline
+ \{\newline
+ \ unsigned short mask;\newline
+ \ \_\_asm\_\_
+\_\_volatile\_\_({\textquotedbl}tpa{\textbackslash}n{\textbackslash}tsei{\textquotedbl}:{\textquotedbl}=d{\textquotedbl}(mask));\newline
+ \}}
+
+\subparagraph{Code for CodeWarrior}
+{\ttfamily
+void unlock (void)\newline
+ \{\newline
+ \ \_\_asm({\textquotedbl}cli{\textquotedbl});\newline
+ \}\newline
+ void lock (void)\newline
+ \{\newline
+ \ unsigned short mask;\newline
+ \ \_\_asm\newline
+ \{\newline
+ \ tpa:tsei:{\textquotedbl}=d{\textquotedbl}(mask);\newline
+ \}\newline
+ \}}
+
+\paragraph{Initialize function}
+\subparagraph{Code for GCC}
+{\ttfamily
+void initCanHCS12 (void)\newline
+ \{ \ \newline
+ \ //Init the HCS12 microcontroler for CanOpen \newline
+ \ initHCS12();\newline
+ \ \ // Init the HCS12 \ CAN driver\newline
+ \ const canBusInit bi0 = \{\newline
+ \ \ \ 0, \ \ \ /* no low power \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */
+\newline
+ \ \ \ 0, \ \ \ /* no time stamp
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 1, \ \ \ /* enable MSCAN
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 0, \ \ \ /* clock source : oscillator (In fact, it is not used)
+\ \ */\newline
+ \ \ \ 0, \ \ \ /* no loop back
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 0, \ \ \ /* no listen only
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 0, \ \ \ /* no low pass filter for wk up */\newline
+ \ CAN\_Baudrates[CAN\_BAUDRATE\_250K],\newline
+ \ \ \ \{\newline
+ \ \ \ \ \ 0x00, \ \ \ /* Filter on 16 bits.\newline
+ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ See Motorola Block Guide V02.14 fig
+4{}-3 */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 0 hight accept all msg
+\ \ \ \ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 0 low accept all msg
+\ \ \ \ \ \ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 1 hight filter all of \ msg
+\ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 1 low filter all of \ msg
+\ \ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 2 hight filter most of \ msg
+*/\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 2 low filter most of \ msg
+\ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 3 hight filter most of \ msg
+*/\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 3 low filter most of \ msg
+\ \ */\newline
+ \ \ \ \}\newline
+ \ \};}
+
+\subparagraph{Code for CodeWarrior}
+{\ttfamily
+void initCanHCS12 (void)\newline
+ \{ \ \newline
+ \ //Init the HCS12 microcontroler for CanOpen \newline
+ \ initHCS12();\newline
+ \ \ // Init the HCS12 \ CAN driver\newline
+ \ const canBusInit bi0 = \{\newline
+ \ \ \ 0, \ \ \ /* no low power \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */
+\newline
+ \ \ \ 0, \ \ \ /* no time stamp
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 1, \ \ \ /* enable MSCAN
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 0, \ \ \ /* clock source : oscillator (In fact, it is not used)
+\ \ */\newline
+ \ \ \ 0, \ \ \ /* no loop back
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 0, \ \ \ /* no listen only
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ */\newline
+ \ \ \ 0, \ \ \ /* no low pass filter for wk up */\newline
+ \ \ \ \{\newline
+ \ \ \ \ 1, /* clksrc */\newline
+ \ \ \ \ 3, /* brp \ \ \ */\newline
+ \ \ \ \ 0, /* sjw \ \ \ */\newline
+ \ \ \ \ 0, /* samp \ \ */\newline
+ \ \ \ \ 1, /* tseg2 \ */\newline
+ \ \ \ \ 12,/* tseg1 \ */\newline
+ \ \ \ \},\newline
+ \ \ \ \{\newline
+ \ \ \ \ \ 0x00, \ \ \ /* Filter on 16 bits.\newline
+ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ See Motorola Block Guide V02.14 fig
+4{}-3 */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 0 hight accept all msg
+\ \ \ \ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 0 low accept all msg
+\ \ \ \ \ \ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 1 hight filter all of \ msg
+\ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 1 low filter all of \ msg
+\ \ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 2 hight filter most of \ msg
+*/\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 2 low filter most of \ msg
+\ \ */\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 3 hight filter most of \ msg
+*/\newline
+ \ \ \ \ \ 0x00, 0xFF, /* filter 3 low filter most of \ msg
+\ \ */\newline
+ \ \ \ \}\newline
+ \ \};}
+
+\subsubsection{Who to use warnings and errors messages ?}
+\paragraph{Warnings messages}
+\begin{longtable}[c]{|p{0.8476598in}|p{0.7761598in}|p{1.0268599in}|p{-0.026640158in}|p{1.0386599in}|p{1.2247599in}|p{1.1761599in}|}
+\hline
+{\bfseries
+DEBUG\_WAR\_CONSOLE \_ON}
+&
+{\bfseries
+DEBUG \_CAN}
+&
+{\bfseries
+PrintMsg{}-WarTo{}-Console}
+&
+
+\bigskip
+&
+{\bfseries
+Printing long message on console }
+&
+\textbf{Printing short message on console.} (number and value only)
+&
+\textbf{Sending number and value in a PDO}., only if the node is a
+slave, in operational state.
+\\\hline
+\endhead
+DEF
+&
+DEF
+&
+1
+&
+
+\bigskip
+&
+
+\bigskip
+&
+yes
+&
+
+\bigskip
+\\\hline
+DEF
+&
+DEF
+&
+0
+&
+
+\bigskip
+&
+yes
+&
+
+\bigskip
+&
+
+\bigskip
+\\\hline
+DEF
+&
+UNDEF
+&
+1
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+\\\hline
+DEF
+&
+UNDEF
+&
+0
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+\\\hline
+UNDEF
+&
+X
+&
+X
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+\\\hline
+\end{longtable}
+
+\bigskip
+
+\paragraph{Errors messages}
+\begin{longtable}[c]{|p{0.8476598in}|p{0.7351598in}|p{0.6511598in}|p{0.7865598in}|p{-0.026640158in}|p{0.8087598in}|p{0.9955599in}|p{1.1858599in}|}
+\hline
+{\bfseries
+DEBUG\_ERR\_CONSOLE \_ON}
+&
+{\bfseries
+DEBUG \_CAN}
+&
+{\bfseries
+PDO \_ERROR }
+&
+{\bfseries
+PrintMsg{}-ErrTo{}-Console}
+&
+
+\bigskip
+&
+{\bfseries
+Printing long message on console}
+&
+\textbf{Printing short message on console.} (number and value only)
+&
+\textbf{Sending number and value in a PDO}., only if the node is a
+slave, in operational state.
+\\\hline
+\endhead
+DEF
+&
+DEF
+&
+X
+&
+1
+&
+
+\bigskip
+&
+
+\bigskip
+&
+yes
+&
+yes
+\\\hline
+DEF
+&
+DEF
+&
+X
+&
+0
+&
+
+\bigskip
+&
+yes
+&
+
+\bigskip
+&
+yes
+\\\hline
+DEF
+&
+UNDEF
+&
+X
+&
+1
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+&
+yes
+\\\hline
+DEF
+&
+UNDEF
+&
+X
+&
+0
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+&
+yes
+\\\hline
+UNDEF
+&
+X
+&
+DEF
+&
+X
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+&
+yes
+\\\hline
+UNDEF
+&
+X
+&
+UNDEF
+&
+X
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+&
+
+\bigskip
+\\\hline
+\end{longtable}
+
+\bigskip
+
+\subsubsection{Does the code works in banked memory ?}
+No. Today it seems that the port of gcc is bogged for using the banked
+memory. So, unfortunately, we are limited to 48 Kbytes of memory code.
+
+\subsubsection{What GCC version are you using ?}
+We are using the stable RPM release 2.2 :
+
+\liststyleLxiii
+\begin{enumerate}
+\item GNU Gcc 3.0.4. Build 20030501
+\item Newlib 1.10.0 Build 20030421
+\item GNU Binutils 2.12.1 Build 20030427
+\end{enumerate}
+\section{Documentation resources}
+\paragraph{CIA : Can in Automation}
+Many documentation on CANopen.
+
+\href{http://www.can-cia.de/}{http://www.can{}-cia.de}
+
+\paragraph{Resources and training in CANopen}
+\href{http://www.esacademy.com/}{http://www.esacademy.com}
+
+\paragraph{Elektronikladen HCS12 T{}-board}
+\href{http://www.elektronikladen.de/en_hcs12tb.html}{http://www.elektronikladen.de/en\_hcs12tb.html}
+
+\paragraph{Gnu gcc compiler for HC12}
+\href{http://m68hc11.serveftp.org/m68hc11_port.php}{http://m68hc11.serveftp.org/m68hc11\_port.php}
+
+\paragraph{Motorola documentation on HC12}
+\href{http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MC9S12DP256}{http://www.freescale.com/webapp/sps/site/prod\_summary.jsp?code=MC9S12DP256}
+
+\paragraph{Lauterbach debugger for HC12}
+\href{http://www.lauterbach.com/}{http://www.lauterbach.com}
+
+\paragraph{Python language}
+\href{http://www.python.org/}{http://www.python.org}
+
+\clearpage\section{About the project}
+\subsection{Contributors }
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/1000020100000258000000832C6FFAB4.png}
+\end{center}
+
+Unit\'e mixte de recherche INRETS{}-LCPC
+
+sur les Interractions V\'ehicule{}-Infrastructure{}-Conducteur
+
+14, route de la mini\`ere
+
+78000 Versailles
+
+FRANCE
+
+Tel : +33 1 40 43 29 01
+
+\href{http://www.inrets.fr/ur/livic}{http://www.inrets.fr/ur/livic}
+
+\textbf{Contributors :} Francis DUPIN
+
+ Camille BOSSARD
+
+ Laurent ROMIEUX
+
+
+\bigskip
+
+ \begin{center}
+ \includegraphics[width=15cm]{Pictures/100002010000013A0000004A96B0C1FF.png}
+\end{center}
+
+LOLITECH
+
+204, rue du Haut du Pin
+
+88470 Saint{}-Michel sur Meurthe
+
+FRANCE
+
+Tel : +33 3 29 52 95 67
+
+\href{http://www.lolitech.fr/}{http://www.lolitech.fr}
+
+{\bfseries
+Contributors : \textmd{Edouard TISSERANT (Original author)}}
+
+{\mdseries
+ Laurent BESSARD}
+
+
+\bigskip
+
+Many thanks to the other contributors for their great work:
+
+\textmd{ }Raphael ZULLIGER
+
+\textmd{ }David DUMINY (st\'e A6R)
+
+\textmd{ }Zakaria BELAMRI
+
+\subsection{Getting support}
+Send your feedback and bug reports to
+\href{mailto:canfestival-devel@lists.sourceforge.net}{canfestival{}-devel@lists.sourceforge.net}.
+
+For commercial support, \ training and specific integration and
+developments, please ask LOLITECH (see contributors).
+
+\subsection{Contributing}
+You are free to contribute your specific interfaces back to the project.
+This way, you can hope to get support from CanFestival users community.
+
+Please send your patch to
+\href{mailto:canfestival-devel@lists.sourceforge.net}{canfestival{}-devel@lists.sourceforge.net}.
+
+Feel free to create some new predefined DS{}-4xx profiles (*.prf) in
+objdictgen/config, as much as possible respectful to the official
+specifications.
+
+\subsection{License}
+All the project is licensed with LGPL. This mean you can link
+CanFestival with any code without being obliged to publish it.
+
+{\ttfamily
+\#This file is part of CanFestival, a library implementing CanOpen
+Stack. \newline
+\# \newline
+\#Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
+\newline
+\# \newline
+\#See COPYING file for copyrights details. \newline
+\# \newline
+\#This library is free software; you can redistribute it and/or \newline
+\#modify it under the terms of the GNU Lesser General Public \newline
+\#License as published by the Free Software Foundation; either \newline
+\#version 2.1 of the License, or (at your option) any later version.
+\newline
+\# \newline
+\#This library is distributed in the hope that it will be useful,
+\newline
+\#but WITHOUT ANY WARRANTY; without even the implied warranty of
+\newline
+\#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \ See the GNU
+\newline
+\#Lesser General Public License for more details. \newline
+\# \newline
+\#You should have received a copy of the GNU Lesser General Public
+\newline
+\#License along with this library; if not, write to the Free Software
+\newline
+\#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+\ 02111{}-1307 \ USA }
+
+
+\bigskip
+\end{document}
--- a/src/dcf.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/dcf.c Tue Jun 05 16:41:38 2007 +0200
@@ -22,12 +22,12 @@
USA
*/
-/*!
+/**
** @file dcf.c
** @author Edouard TISSERANT and Francis DUPIN
** @date Mon Jun 4 17:06:12 2007
**
-** @brief
+** @brief EXEMPLE OF SOMMARY
**
**
*/
@@ -37,18 +37,30 @@
#include "sysdep.h"
-
+/**
+**
+**
+** @param d fuck fuck fuck
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+** @param endianize
+*/
extern UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
const indextable *ptrTable;
-/*!
+/**
**
**
** @param d
** @param nodeId
-**/
+*/
static void CheckSDOAndContinue(CO_Data* d, UNS8 nodeId)
{
UNS32 abortCode;
@@ -63,14 +75,14 @@
decompo_dcf(d,nodeId);
}
-/*!
+/**
**
**
** @param d
** @param nodeId
**
** @return
-**/
+*/
UNS32 decompo_dcf(CO_Data* d,UNS8 nodeId)
{
UNS32 errorCode;
@@ -86,7 +98,7 @@
return errorCode;
}
- /*Loop on all Nodes supported in DCF subindexes*/
+ /** Loop on all Nodes supported in DCF subindexes*/
while (nodeId < ptrTable->bSubCount){
UNS32 nb_targets;
@@ -103,27 +115,27 @@
nb_targets = UNS32_LE(*((UNS32*)dcf));
}
- // condition on consise DCF string for NodeID, if big enough
+ /** condition on consise DCF string for NodeID, if big enough */
if((UNS8*)d->dcf_cursor + 7 < (UNS8*)dcfend && d->dcf_count_targets < nb_targets)
{
- // pointer to the DCF string for NodeID
+ /** pointer to the DCF string for NodeID */
target_Index = UNS16_LE(*((UNS16*)(d->dcf_cursor))); d->dcf_cursor += 2;
target_Subindex = *((UNS8*)(((UNS8*)d->dcf_cursor)++));
target_Size = UNS32_LE(*((UNS32*)(d->dcf_cursor))); d->dcf_cursor += 4;
- /*printf("Master : ConfigureSlaveNode %2.2x (Concise
+ /* printf("Master : ConfigureSlaveNode %2.2x (Concise
DCF)\n",nodeId);*/
- res = _writeNetworkDict(d, /*CO_Data* d*/
- nodeId, /*UNS8 nodeId*/
- target_Index, /*UNS16 index*/
- target_Subindex, /*UNS8 subindex*/
- target_Size, /*UNS8 count*/
- 0, /*UNS8 dataType*/
- d->dcf_cursor,/*void *data*/
- CheckSDOAndContinue,/*SDOCallback_t
+ res = _writeNetworkDict(d, /** CO_Data* d*/
+ nodeId, /** UNS8 nodeId*/
+ target_Index, /** UNS16 index*/
+ target_Subindex, /** UNS8 subindex*/
+ target_Size, /** UNS8 count*/
+ 0, /** UNS8 dataType*/
+ d->dcf_cursor,/** void *data*/
+ CheckSDOAndContinue,/** SDOCallback_t
Callback*/
- 0); /* no endianize*/
- /*Push d->dcf_cursor to the end of data*/
+ 0); /** no endianize*/
+ /** Push d->dcf_cursor to the end of data*/
d->dcf_cursor += target_Size;
d->dcf_count_targets++;
@@ -133,7 +145,7 @@
nodeId++;
d->dcf_cursor = NULL;
}
- /* Switch Master to preOperational state */
+ /** Switch Master to preOperational state */
(*d->preOperational)();
}
--- a/src/lifegrd.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/lifegrd.c Tue Jun 05 16:41:38 2007 +0200
@@ -23,7 +23,7 @@
*/
/*!
-** @file filegrd.c
+** @file lifegrd.c
** @author Edouard TISSERANT
** @date Mon Jun 4 17:19:24 2007
**
@@ -36,31 +36,12 @@
#include "lifegrd.h"
#include "canfestival.h"
-/*! Prototypes for internals functions
-**
-**
-** @param d
-** @param id
-**/
+
void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id);
-/*!
-**
-**
-** @param d
-** @param id
-**/
+
void ProducerHearbeatAlarm(CO_Data* d, UNS32 id);
-/*!
-**
-**
-** @param d
-** @param unsused_indextable
-** @param unsused_bSubindex
-**
-** @return
-**/
UNS32 OnHearbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex);
/*!
@@ -77,8 +58,8 @@
return networkNodeState;
}
-/*! The Consumer Timer Callback
-**
+/*!
+** The Consumer Timer Callback
**
** @param d
** @param id
--- a/src/nmtMaster.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/nmtMaster.c Tue Jun 05 16:41:38 2007 +0200
@@ -1,71 +1,103 @@
/*
-This file is part of CanFestival, a library implementing CanOpen Stack.
+ This file is part of CanFestival, a library implementing CanOpen
+ Stack.
-Copyright (C): Edouard TISSERANT and Francis DUPIN
+ Copyright (C): Edouard TISSERANT and Francis DUPIN
-See COPYING file for copyrights details.
+ See COPYING file for copyrights details.
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
*/
-
+/*!
+** @file nmtMaster.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 08:47:18 2007
+**
+** @brief
+**
+**
+*/
#include "nmtMaster.h"
#include "canfestival.h"
-/******************************************************************************/
+/*!
+**
+**
+** @param d
+** @param Node_ID
+** @param cs
+**
+** @return
+**/
UNS8 masterSendNMTstateChange(CO_Data* d, UNS8 Node_ID, UNS8 cs)
{
Message m;
MSG_WAR(0x3501, "Send_NMT cs : ", cs);
MSG_WAR(0x3502, " to node : ", Node_ID);
- /* message configuration */
+ /*! message configuration */
m.cob_id.w = 0x0000; /*(NMT) << 7*/
m.rtr = NOT_A_REQUEST;
m.len = 2;
m.data[0] = cs;
m.data[1] = Node_ID;
-
+
return canSend(d->canHandle,&m);
}
-/****************************************************************************/
+/*!
+**
+**
+** @param d
+** @param nodeId
+**
+** @return
+**/
UNS8 masterSendNMTnodeguard(CO_Data* d, UNS8 nodeId)
{
Message m;
-
+
MSG_WAR(0x3503, "Send_NODE_GUARD to node : ", nodeId);
-
+
/* message configuration */
m.cob_id.w = nodeId | (NODE_GUARD << 7);
m.rtr = REQUEST;
m.len = 1;
-
+
return canSend(d->canHandle,&m);
}
-/******************************************************************************/
+/*!
+**
+**
+** @param d
+** @param nodeId
+**/
void masterRequestNodeState(CO_Data* d, UNS8 nodeId)
{
- /* FIXME: should warn for bad toggle bit. */
+ /*! FIXME: should warn for bad toggle bit. */
- /* NMTable configuration to indicate that the master is waiting
- * for a Node_Guard frame from the slave whose node_id is ID */
- d->NMTable[nodeId] = Unknown_state; /* A state that does not exist */
+ /*! NMTable configuration to indicate that the master is waiting
+ for a Node_Guard frame from the slave whose node_id is ID
+ */
+ d->NMTable[nodeId] = Unknown_state; /*! A state that does not exist
+ */
- if (nodeId == 0) { /* NMT broadcast */
+ if (nodeId == 0) { /*! NMT broadcast */
UNS8 i = 0;
for (i = 0 ; i < NMT_MAX_NODE_ID ; i++) {
d->NMTable[i] = Unknown_state;
@@ -74,11 +106,3 @@
masterSendNMTnodeguard(d,nodeId);
}
-
-
-
-
-
-
-
-
--- a/src/nmtSlave.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/nmtSlave.c Tue Jun 05 16:41:38 2007 +0200
@@ -1,90 +1,111 @@
/*
-This file is part of CanFestival, a library implementing CanOpen Stack.
+ This file is part of CanFestival, a library implementing CanOpen
+ Stack.
-Copyright (C): Edouard TISSERANT and Francis DUPIN
+ Copyright (C): Edouard TISSERANT and Francis DUPIN
-See COPYING file for copyrights details.
+ See COPYING file for copyrights details.
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
*/
-
+/*!
+** @file nmtSlave.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 08:50:53 2007
+**
+** @brief
+**
+**
+*/
#include "nmtSlave.h"
#include "states.h"
#include "canfestival.h"
-/*******************************************************************)*********/
-/* put the slave in the state wanted by the master */
+/*!
+** put the slave in the state wanted by the master
+**
+** @param d
+** @param m
+**/
void proceedNMTstateChange(CO_Data* d, Message *m)
{
if( d->nodeState == Pre_operational ||
d->nodeState == Operational ||
d->nodeState == Stopped ) {
-
+
MSG_WAR(0x3400, "NMT received. for node : ", (*m).data[1]);
-
- /* Check if this NMT-message is for this node */
- /* byte 1 = 0 : all the nodes are concerned (broadcast) */
-
+
+ /*! Check if this NMT-message is for this node */
+ /*! byte 1 = 0 : all the nodes are concerned (broadcast) */
+
if( ( (*m).data[1] == 0 ) || ( (*m).data[1] == *d->bDeviceNodeId ) ){
-
- switch( (*m).data[0]){ /* command specifier (cs) */
+
+ switch( (*m).data[0]){ /*! command specifier (cs) */
case NMT_Start_Node:
if ( (d->nodeState == Pre_operational) || (d->nodeState == Stopped) )
setState(d,Operational);
- break;
-
+ break;
+
case NMT_Stop_Node:
if ( d->nodeState == Pre_operational ||
- d->nodeState == Operational )
+ d->nodeState == Operational )
setState(d,Stopped);
break;
-
+
case NMT_Enter_PreOperational:
- if ( d->nodeState == Operational ||
- d->nodeState == Stopped )
- setState(d,Pre_operational);
+ if ( d->nodeState == Operational ||
+ d->nodeState == Stopped )
+ setState(d,Pre_operational);
break;
-
+
case NMT_Reset_Node:
- setState(d,Initialisation);
+ setState(d,Initialisation);
break;
-
+
case NMT_Reset_Comunication:
- setState(d,Initialisation);
+ setState(d,Initialisation);
break;
-
- }/* end switch */
-
- }/* end if( ( (*m).data[1] == 0 ) || ( (*m).data[1] == bDeviceNodeId ) ) */
+
+ }/*! end switch */
+
+ }/*! end if( ( (*m).data[1] == 0 ) || ( (*m).data[1] ==
+ bDeviceNodeId ) ) */
}
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+**
+** @return
+**/
UNS8 slaveSendBootUp(CO_Data* d)
{
Message m;
-
+
MSG_WAR(0x3407, "Send a Boot-Up msg ", 0);
-
- /* message configuration */
+
+ /*! message configuration */
m.cob_id.w = NODE_GUARD << 7 | *d->bDeviceNodeId;
m.rtr = NOT_A_REQUEST;
m.len = 1;
m.data[0] = 0x00;
-
+
return canSend(d->canHandle,&m);
}
--- a/src/objacces.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/objacces.c Tue Jun 05 16:41:38 2007 +0200
@@ -1,24 +1,38 @@
/*
-This file is part of CanFestival, a library implementing CanOpen Stack.
-
-Copyright (C): Edouard TISSERANT and Francis DUPIN
-
-See COPYING file for copyrights details.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ This file is part of CanFestival, a library implementing CanOpen
+ Stack.
+
+ Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+ See COPYING file for copyrights details.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
*/
+/*!
+** @file objacces.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 08:55:23 2007
+**
+** @brief
+**
+**
+*/
+
+
+
/* #define DEBUG_WAR_CONSOLE_ON */
/* #define DEBUG_ERR_CONSOLE_ON */
@@ -27,53 +41,77 @@
#include "objacces.h"
-
-UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
- UNS8 sizeDataDict, UNS8 sizeDataGiven, UNS32 code)
+/*!
+**
+**
+** @param index
+** @param subIndex
+** @param sizeDataDict
+** @param sizeDataGiven
+** @param code
+**
+** @return
+**/
+UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
+ UNS8 sizeDataDict, UNS8 sizeDataGiven, UNS32 code)
{
#ifdef DEBUG_WAR_CONSOLE_ON
MSG_WAR(0x2B09,"Dictionary index : ", index);
MSG_WAR(0X2B10," subindex : ", subIndex);
switch (code) {
- case OD_NO_SUCH_OBJECT:
- MSG_WAR(0x2B11,"Index not found ", index);
- break;
- case OD_NO_SUCH_SUBINDEX :
- MSG_WAR(0x2B12,"SubIndex not found ", subIndex);
- break;
- case OD_WRITE_NOT_ALLOWED :
- MSG_WAR(0x2B13,"Write not allowed, data is read only ", index);
- break;
- case OD_LENGTH_DATA_INVALID :
- MSG_WAR(0x2B14,"Conflict size data. Should be (bytes) : ", sizeDataDict);
- MSG_WAR(0x2B15,"But you have given the size : ", sizeDataGiven);
- break;
- case OD_NOT_MAPPABLE :
- MSG_WAR(0x2B16,"Not mappable data in a PDO at index : ", index);
- break;
- case OD_VALUE_TOO_LOW :
- MSG_WAR(0x2B17,"Value range error : value too low. SDOabort : ", code);
- break;
- case OD_VALUE_TOO_HIGH :
- MSG_WAR(0x2B18,"Value range error : value too high. SDOabort : ", code);
- break;
+ case OD_NO_SUCH_OBJECT:
+ MSG_WAR(0x2B11,"Index not found ", index);
+ break;
+ case OD_NO_SUCH_SUBINDEX :
+ MSG_WAR(0x2B12,"SubIndex not found ", subIndex);
+ break;
+ case OD_WRITE_NOT_ALLOWED :
+ MSG_WAR(0x2B13,"Write not allowed, data is read only ", index);
+ break;
+ case OD_LENGTH_DATA_INVALID :
+ MSG_WAR(0x2B14,"Conflict size data. Should be (bytes) : ", sizeDataDict);
+ MSG_WAR(0x2B15,"But you have given the size : ", sizeDataGiven);
+ break;
+ case OD_NOT_MAPPABLE :
+ MSG_WAR(0x2B16,"Not mappable data in a PDO at index : ", index);
+ break;
+ case OD_VALUE_TOO_LOW :
+ MSG_WAR(0x2B17,"Value range error : value too low. SDOabort : ", code);
+ break;
+ case OD_VALUE_TOO_HIGH :
+ MSG_WAR(0x2B18,"Value range error : value too high. SDOabort : ", code);
+ break;
default :
MSG_WAR(0x2B20, "Unknown error code : ", code);
}
#endif
- return 0;
-}
-
-
-UNS32 _getODentry( CO_Data* d,
- UNS16 wIndex,
- UNS8 bSubindex,
- void * pDestData,
- UNS8 * pExpectedSize,
- UNS8 * pDataType,
- UNS8 checkAccess,
- UNS8 endianize)
-{ /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
+ return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pDestData
+** @param pExpectedSize
+** @param pDataType
+** @param checkAccess
+** @param endianize
+**
+** @return
+**/
+UNS32 _getODentry( CO_Data* d,
+ UNS16 wIndex,
+ UNS8 bSubindex,
+ void * pDestData,
+ UNS8 * pExpectedSize,
+ UNS8 * pDataType,
+ UNS8 checkAccess,
+ UNS8 endianize)
+{ /*! DO NOT USE MSG_ERR because the macro may send a PDO -> infinite
+ loop if it fails. */
UNS32 errorCode;
UNS8 szData;
const indextable *ptrTable;
@@ -88,103 +126,144 @@
accessDictionaryError(wIndex, bSubindex, 0, 0, OD_NO_SUCH_SUBINDEX);
return OD_NO_SUCH_SUBINDEX;
}
-
+
if (checkAccess && !(ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
- MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
+ MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
accessDictionaryError(wIndex, bSubindex, 0, 0, OD_WRITE_NOT_ALLOWED);
return OD_READ_NOT_ALLOWED;
}
*pDataType = ptrTable->pSubindex[bSubindex].bDataType;
- szData = ptrTable->pSubindex[bSubindex].size;
-
- if( *pExpectedSize == 0 ||
- *pExpectedSize == szData ||
- (*pDataType == visible_string && *pExpectedSize < szData)) {/* We allow to fetch a shorter string than expected */
-
+ szData = ptrTable->pSubindex[bSubindex].size;
+
+ if(*pExpectedSize == 0 ||
+ *pExpectedSize == szData ||
+ (*pDataType == visible_string && *pExpectedSize < szData)) {
+ /*! We
+ allow to fetch a shorter string than expected */
+
# ifdef CANOPEN_BIG_ENDIAN
- if(endianize && *pDataType > boolean && *pDataType < visible_string) {
- /* data must be transmited with low byte first */
- UNS8 i, j = 0;
- MSG_WAR(boolean, "data type ", *pDataType);
- MSG_WAR(visible_string, "data type ", *pDataType);
- for ( i = szData ; i > 0 ; i--) {
- MSG_WAR(i," ", j);
- ((UNS8*)pDestData)[j++] =
- ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
- }
- }
- else /* It it is a visible string no endianisation to perform */
- memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
+ if(endianize && *pDataType > boolean && *pDataType < visible_string) {
+ /*! data must be transmited with low byte first */
+ UNS8 i, j = 0;
+ MSG_WAR(boolean, "data type ", *pDataType);
+ MSG_WAR(visible_string, "data type ", *pDataType);
+ for ( i = szData ; i > 0 ; i--) {
+ MSG_WAR(i," ", j);
+ ((UNS8*)pDestData)[j++] =
+ ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
+ }
+ }
+ else /*! It it is a visible string no endianisation to perform */
+ memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
# else
- memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
+ memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
# endif
-
- *pExpectedSize = szData;
+
+ *pExpectedSize = szData;
#if 0
- /* Me laisser ça, please ! (FD) */
- {
- UNS8 i;
- for (i = 0 ; i < 10 ; i++) {
- MSG_WAR(*pExpectedSize, "dic data= ",
- *(UNS8 *)(ptrTable->pSubindex[bSubindex].pObject + i));
- }
-
- }
+ /*! Me laisser a, please ! (FD) */
+ {
+ UNS8 i;
+ for (i = 0 ; i < 10 ; i++) {
+ MSG_WAR(*pExpectedSize, "dic data= ",
+ *(UNS8 *)(ptrTable->pSubindex[bSubindex].pObject + i));
+ }
+
+ }
#endif
- return OD_SUCCESSFUL;
- }
- else { /* Error ! */
- *pExpectedSize = szData;
- accessDictionaryError(wIndex, bSubindex, szData,
- *pExpectedSize, OD_LENGTH_DATA_INVALID);
- return OD_LENGTH_DATA_INVALID;
- }
-}
-
-UNS32 getODentry( CO_Data* d,
+ return OD_SUCCESSFUL;
+ }
+ else { /*! Error ! */
+ *pExpectedSize = szData;
+ accessDictionaryError(wIndex, bSubindex, szData,
+ *pExpectedSize, OD_LENGTH_DATA_INVALID);
+ return OD_LENGTH_DATA_INVALID;
+ }
+}
+
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pDestData
+** @param pExpectedSize
+** @param pDataType
+** @param checkAccess
+**
+** @return
+**/
+UNS32 getODentry( CO_Data* d,
UNS16 wIndex,
- UNS8 bSubindex,
- void * pDestData,
- UNS8 * pExpectedSize,
- UNS8 * pDataType,
- UNS8 checkAccess)
-{
- return _getODentry( d,
- wIndex,
- bSubindex,
- pDestData,
- pExpectedSize,
- pDataType,
- checkAccess,
- 1);//endianize
-}
-
-UNS32 readLocalDict( CO_Data* d,
- UNS16 wIndex,
- UNS8 bSubindex,
- void * pDestData,
- UNS8 * pExpectedSize,
- UNS8 * pDataType,
- UNS8 checkAccess)
-{
- return _getODentry( d,
- wIndex,
- bSubindex,
- pDestData,
- pExpectedSize,
- pDataType,
- checkAccess,
- 0);//do not endianize
-}
-
-UNS32 _setODentry( CO_Data* d,
- UNS16 wIndex,
- UNS8 bSubindex,
- void * pSourceData,
- UNS8 * pExpectedSize,
- UNS8 checkAccess,
- UNS8 endianize)
+ UNS8 bSubindex,
+ void * pDestData,
+ UNS8 * pExpectedSize,
+ UNS8 * pDataType,
+ UNS8 checkAccess)
+{
+ return _getODentry( d,
+ wIndex,
+ bSubindex,
+ pDestData,
+ pExpectedSize,
+ pDataType,
+ checkAccess,
+ 1);//endianize
+}
+
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pDestData
+** @param pExpectedSize
+** @param pDataType
+** @param checkAccess
+**
+** @return
+**/
+UNS32 readLocalDict( CO_Data* d,
+ UNS16 wIndex,
+ UNS8 bSubindex,
+ void * pDestData,
+ UNS8 * pExpectedSize,
+ UNS8 * pDataType,
+ UNS8 checkAccess)
+{
+ return _getODentry( d,
+ wIndex,
+ bSubindex,
+ pDestData,
+ pExpectedSize,
+ pDataType,
+ checkAccess,
+ 0);//do not endianize
+}
+
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pSourceData
+** @param pExpectedSize
+** @param checkAccess
+** @param endianize
+**
+** @return
+**/
+UNS32 _setODentry( CO_Data* d,
+ UNS16 wIndex,
+ UNS8 bSubindex,
+ void * pSourceData,
+ UNS8 * pExpectedSize,
+ UNS8 checkAccess,
+ UNS8 endianize)
{
UNS8 szData;
UNS8 dataType;
@@ -197,112 +276,161 @@
return errorCode;
if( ptrTable->bSubCount <= bSubindex ) {
- /* Subindex not found */
+ /*! Subindex not found */
accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
return OD_NO_SUCH_SUBINDEX;
}
if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
- MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
+ MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
return OD_WRITE_NOT_ALLOWED;
}
- dataType = ptrTable->pSubindex[bSubindex].bDataType;
- szData = ptrTable->pSubindex[bSubindex].size;
+ dataType = ptrTable->pSubindex[bSubindex].bDataType;
+ szData = ptrTable->pSubindex[bSubindex].size;
if( *pExpectedSize == 0 ||
- *pExpectedSize == szData ||
- (dataType == visible_string && *pExpectedSize < szData)) /* We allow to store a shorter string than entry size */
- {
- #ifdef CANOPEN_BIG_ENDIAN
- if(endianize && dataType > boolean && dataType < visible_string)
- {
- /* we invert the data source directly. This let us do range testing without */
- /* additional temp variable */
- UNS8 i;
- for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
- {
- UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
- ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
- ((UNS8 *)pSourceData)[i] = tmp;
- }
- }
- #endif
+ *pExpectedSize == szData ||
+ (dataType == visible_string && *pExpectedSize < szData)) /* We
+ allow to store a shorter string than entry size */
+ {
+#ifdef CANOPEN_BIG_ENDIAN
+ if(endianize && dataType > boolean && dataType < visible_string)
+ {
+ /*! we invert the data source directly. This let us do range
+ testing without */
+ /*! additional temp variable */
+ UNS8 i;
+ for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
+ {
+ UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
+ ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
+ ((UNS8 *)pSourceData)[i] = tmp;
+ }
+ }
+#endif
errorCode = (*d->valueRangeTest)(dataType, pSourceData);
if (errorCode) {
- accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
- return errorCode;
+ accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
+ return errorCode;
}
memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
*pExpectedSize = szData;
-
- /* Callbacks */
+
+ /*! Callbacks */
if(Callback && Callback[bSubindex]){
- (*Callback[bSubindex])(d, ptrTable, bSubindex);
+ (*Callback[bSubindex])(d, ptrTable, bSubindex);
}
-
- /* TODO : Store dans NVRAM */
+
+ /*! TODO : Store dans NVRAM */
if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
- (*d->storeODSubIndex)(wIndex, bSubindex);
+ (*d->storeODSubIndex)(wIndex, bSubindex);
}
return OD_SUCCESSFUL;
- }else{
+ }else{
*pExpectedSize = szData;
accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
return OD_LENGTH_DATA_INVALID;
- }
-}
-
-UNS32 setODentry( CO_Data* d,
+ }
+}
+
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pSourceData
+** @param pExpectedSize
+** @param checkAccess
+**
+** @return
+**/
+UNS32 setODentry( CO_Data* d,
UNS16 wIndex,
- UNS8 bSubindex,
- void * pSourceData,
- UNS8 * pExpectedSize,
- UNS8 checkAccess)
-{
- return _setODentry( d,
- wIndex,
- bSubindex,
- pSourceData,
- pExpectedSize,
- checkAccess,
- 1);//endianize
-}
-
-UNS32 writeLocalDict( CO_Data* d,
- UNS16 wIndex,
- UNS8 bSubindex,
- void * pSourceData,
- UNS8 * pExpectedSize,
- UNS8 checkAccess)
-{
- return _setODentry( d,
- wIndex,
- bSubindex,
- pSourceData,
- pExpectedSize,
- checkAccess,
- 0);//do not endianize
-}
-
-
-
-
+ UNS8 bSubindex,
+ void * pSourceData,
+ UNS8 * pExpectedSize,
+ UNS8 checkAccess)
+{
+ return _setODentry( d,
+ wIndex,
+ bSubindex,
+ pSourceData,
+ pExpectedSize,
+ checkAccess,
+ 1);//endianize
+}
+
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pSourceData
+** @param pExpectedSize
+** @param checkAccess
+**
+** @return
+**/
+UNS32 writeLocalDict( CO_Data* d,
+ UNS16 wIndex,
+ UNS8 bSubindex,
+ void * pSourceData,
+ UNS8 * pExpectedSize,
+ UNS8 checkAccess)
+{
+ return _setODentry( d,
+ wIndex,
+ bSubindex,
+ pSourceData,
+ pExpectedSize,
+ checkAccess,
+ 0);//do not endianize
+}
+
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param errorCode
+** @param Callback
+**
+** @return
+**/
const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
{
return (*d->scanIndexOD)(wIndex, errorCode, Callback);
}
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param Callback
+**
+** @return
+**/
UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
{
- UNS32 errorCode;
- ODCallback_t *CallbackList;
-
- scanIndexOD (d, wIndex, &errorCode, &CallbackList);
- if(errorCode == OD_SUCCESSFUL && CallbackList)
- CallbackList[bSubindex] = Callback;
- return errorCode;
-}
-
+ UNS32 errorCode;
+ ODCallback_t *CallbackList;
+
+ scanIndexOD (d, wIndex, &errorCode, &CallbackList);
+ if(errorCode == OD_SUCCESSFUL && CallbackList)
+ CallbackList[bSubindex] = Callback;
+ return errorCode;
+}
+
+/*!
+**
+**
+** @param wIndex
+** @param bSubindex
+**/
void _storeODSubIndex (UNS16 wIndex, UNS8 bSubindex){}
--- a/src/pdo.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/pdo.c Tue Jun 05 16:41:38 2007 +0200
@@ -1,45 +1,56 @@
/*
-This file is part of CanFestival, a library implementing CanOpen Stack.
-
-Copyright (C): Edouard TISSERANT and Francis DUPIN
-
-See COPYING file for copyrights details.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ This file is part of CanFestival, a library implementing CanOpen
+ Stack.
+
+ Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+ See COPYING file for copyrights details.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
*/
#include "pdo.h"
#include "objacces.h"
#include "canfestival.h"
-/****************************************************************************/
+/*!
+** @file pdo.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
UNS8 sendPDO(CO_Data* d, s_PDO pdo, UNS8 req)
{
UNS8 i;
if( d->nodeState == Operational ) {
Message m;
- /* Message copy for sending */
- m.cob_id.w = pdo.cobId & 0x7FF; /* Because the cobId is 11 bytes length */
+ /*! Message copy for sending */
+ m.cob_id.w = pdo.cobId & 0x7FF; /*! Because the cobId is 11 bytes
+ length */
if ( req == NOT_A_REQUEST ) {
UNS8 i;
m.rtr = NOT_A_REQUEST;
m.len = pdo.len;
- /* memcpy(&m.data, &pdo.data, m.len); */
- /* This Memcpy depends on packing structure. Avoid */
+ /*! memcpy(&m.data, &pdo.data, m.len); */
+ /*! This Memcpy depends on packing structure. Avoid */
for (i = 0 ; i < pdo.len ; i++)
- m.data[i] = pdo.data[i];
+ m.data[i] = pdo.data[i];
}
else {
m.rtr = REQUEST;
@@ -51,27 +62,34 @@
for (i = 0 ; i < m.len ; i++) {
MSG_WAR(0x3903," data : ", m.data[i]);
}
-
+
return canSend(d->canHandle,&m);
- } /* end if */
+ } /*! end if */
return 0xFF;
}
-/***************************************************************************/
-UNS8 PDOmGR(CO_Data* d, UNS32 cobId) /* PDO Manager */
+/*!
+** PDO Manager
+**
+** @param d
+** @param cobId
+**
+** @return
+**/
+UNS8 PDOmGR(CO_Data* d, UNS32 cobId)
{
UNS8 res;
UNS8 i;
s_PDO pdo;
MSG_WAR(0x3905, "PDOmGR",0);
-
- /* if PDO is waiting for transmission,
- preparation of the message to send */
- pdo.cobId = cobId;
- pdo.len = d->process_var.count;
- /* memcpy(&(pdo.data), &(process_var.data), pdo.len); */
- /* Ce memcpy devrait être portable */
+
+ /*! if PDO is waiting for transmission,
+ preparation of the message to send */
+ pdo.cobId = cobId;
+ pdo.len = d->process_var.count;
+ /*! memcpy(&(pdo.data), &(process_var.data), pdo.len); */
+ /* Ce memcpy devrait tre portable */
for ( i = 0 ; i < pdo.len ; i++)
pdo.data[i] = d->process_var.data[i];
@@ -94,7 +112,8 @@
/* pointer to the var which is mapped to a pdo */
/* void * pMappedAppObject = NULL; */
/* pointer fo the var which holds the mapping parameter of an mapping entry */
- UNS32 * pMappingParameter = NULL;
+
+ UNS32 * pMappingParameter = NULL;
UNS8 Size;
UNS8 dataType;
@@ -106,95 +125,112 @@
subInd=(UNS8)0x00;
offset = 0x00;
ind = index - 0x1800;
-
+
MSG_WAR(0x3910,"Prepare PDO to send index :", index);
- /* only operational state allows PDO transmission */
+ /*! only operational state allows PDO transmission */
if( d->nodeState != Operational ) {
MSG_WAR(0x2911, "Unable to send the PDO (node not in OPERATIONAL mode). Node : ", index);
return 0xFF;
}
offsetObjdictPrm = d->firstIndex->PDO_TRS;
offsetObjdict = d->firstIndex->PDO_TRS_MAP;
-
+
if (offsetObjdictPrm && offsetObjdict)
- {
- /* get mapped objects number to transmit with this PDO */
- pMappingCount = (d->objdict + offsetObjdict + ind)->pSubindex[0].pObject;
- MSG_WAR(0x3912, "Nb maped objects : ",* pMappingCount);
- MSG_WAR(0x3913, " at index : ", 0x1A00 + ind);
- while (subInd < *pMappingCount) { /* Loop on mapped variables */
- /* get mapping parameters */
- pMappingParameter = (d->objdict + offsetObjdict + ind)->pSubindex[subInd + 1].pObject;
- MSG_WAR(0x3914, "Get the mapping at index : ", (UNS16)0x1A00 + ind);
- MSG_WAR(0x3915, " subIndex : ", subInd + 1);
- MSG_WAR(0x3916, " value : ", *(UNS32 *)pMappingParameter);
- /* Get the mapped variable */
- Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
- objDict = getODentry(d, (UNS16)((*pMappingParameter) >> 16),
- (UNS8)(((*pMappingParameter) >> 8 ) & 0x000000FF),
- (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
-
- if (objDict != OD_SUCCESSFUL) {
- MSG_WAR(0x2919, "error accessing to the mapped var : ", subInd + 1);
- MSG_WAR(0x2920, " Mapped at index : ", (*pMappingParameter) >> 16);
- MSG_WAR(0x2921, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
- return 0xFF;
- }
-
- offset += Size;
- d->process_var.count = offset;
- subInd++;
- }/* end Loop on mapped variables */
- }
+ {
+ /*! get mapped objects number to transmit with this PDO */
+ pMappingCount = (d->objdict + offsetObjdict + ind)->pSubindex[0].pObject;
+ MSG_WAR(0x3912, "Nb maped objects : ",* pMappingCount);
+ MSG_WAR(0x3913, " at index : ", 0x1A00 + ind);
+ while (subInd < *pMappingCount) { /*! Loop on mapped variables */
+ /*! get mapping parameters */
+ pMappingParameter = (d->objdict + offsetObjdict + ind)->pSubindex[subInd + 1].pObject;
+ MSG_WAR(0x3914, "Get the mapping at index : ", (UNS16)0x1A00 + ind);
+ MSG_WAR(0x3915, " subIndex : ", subInd + 1);
+ MSG_WAR(0x3916, " value : ", *(UNS32 *)pMappingParameter);
+ /*! Get the mapped variable */
+ Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
+ objDict = getODentry(d, (UNS16)((*pMappingParameter) >> 16),
+ (UNS8)(((*pMappingParameter) >> 8 ) & 0x000000FF),
+ (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
+
+ if (objDict != OD_SUCCESSFUL) {
+ MSG_WAR(0x2919, "error accessing to the mapped var : ", subInd + 1);
+ MSG_WAR(0x2920, " Mapped at index : ", (*pMappingParameter) >> 16);
+ MSG_WAR(0x2921, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
+ return 0xFF;
+ }
+
+ offset += Size;
+ d->process_var.count = offset;
+ subInd++;
+ }/*! end Loop on mapped variables */
+ }
return 0;
}
#endif
-/**************************************************************************/
+
+/*!
+**
+**
+** @param d
+** @param cobId
+**
+** @return
+**/
UNS8 sendPDOrequest( CO_Data* d, UNS32 cobId )
-{
- UNS32 * pwCobId;
+{
+ UNS32 * pwCobId;
UNS16 offset;
UNS16 lastIndex;
UNS8 err;
- MSG_WAR(0x3930, "sendPDOrequest ",0);
- /* Sending the request only if the cobid have been found on the PDO receive */
- /* part dictionary */
+ MSG_WAR(0x3930, "sendPDOrequest ",0);
+ /*! Sending the request only if the cobid have been found on the PDO
+ receive */
+ /*! part dictionary */
offset = d->firstIndex->PDO_RCV;
lastIndex = d->lastIndex->PDO_RCV;
if (offset)
- while (offset <= lastIndex) {
- /*get the CobId*/
- pwCobId = d->objdict[offset].pSubindex[1].pObject;
-
- if ( *pwCobId == cobId ) {
- s_PDO pdo;
- pdo.cobId = *pwCobId;
- pdo.len = 0;
- err = sendPDO(d, pdo, REQUEST);
- return err;
- }
- offset++;
- }
- MSG_WAR(0x1931, "sendPDOrequest : COBID not found : ", cobId);
+ while (offset <= lastIndex) {
+ /*! get the CobId*/
+ pwCobId = d->objdict[offset].pSubindex[1].pObject;
+
+ if ( *pwCobId == cobId ) {
+ s_PDO pdo;
+ pdo.cobId = *pwCobId;
+ pdo.len = 0;
+ err = sendPDO(d, pdo, REQUEST);
+ return err;
+ }
+ offset++;
+ }
+ MSG_WAR(0x1931, "sendPDOrequest : COBID not found : ", cobId);
return 0xFF;
}
-
-/***********************************************************************/
+/*!
+**
+**
+** @param d
+** @param m
+**
+** @return
+**/
UNS8 proceedPDO(CO_Data* d, Message *m)
-{
+{
UNS8 numPdo;
- UNS8 numMap; /* Number of the mapped varable */
+ UNS8 numMap; /*! Number of the mapped varable */
UNS8 i;
- UNS8 * pMappingCount = NULL; /* count of mapped objects... */
- /* pointer to the var which is mapped to a pdo... */
-/* void * pMappedAppObject = NULL; */
- /* pointer fo the var which holds the mapping parameter of an mapping entry */
- UNS32 * pMappingParameter = NULL;
- UNS8 * pTransmissionType = NULL; /* pointer to the transmission type */
+ UNS8 * pMappingCount = NULL; /*! count of mapped objects... */
+ /*! pointer to the var which is mapped to a pdo... */
+ /*! void * pMappedAppObject = NULL; */
+ /*! pointer fo the var which holds the mapping parameter of an
+ mapping entry */
+ UNS32 * pMappingParameter = NULL;
+ UNS8 * pTransmissionType = NULL; /*! pointer to the transmission
+ type */
UNS32 * pwCobId = NULL;
UNS8 Size;
UNS8 dataType;
@@ -204,239 +240,270 @@
UNS16 offsetObjdict;
UNS16 lastIndex;
status = state1;
-
- MSG_WAR(0x3935, "proceedPDO, cobID : ", ((*m).cob_id.w & 0x7ff));
+
+ MSG_WAR(0x3935, "proceedPDO, cobID : ", ((*m).cob_id.w & 0x7ff));
offset = 0x00;
numPdo = 0;
numMap = 0;
- if((*m).rtr == NOT_A_REQUEST ) { /* The PDO received is not a request. */
+ if((*m).rtr == NOT_A_REQUEST ) { /*! The PDO received is not a
+ request. */
offsetObjdict = d->firstIndex->PDO_RCV;
lastIndex = d->lastIndex->PDO_RCV;
-
- /* study of all the PDO stored in the dictionary */
+
+ /*! study of all the PDO stored in the dictionary */
if(offsetObjdict)
- while (offsetObjdict <= lastIndex) {
-
- switch( status ) {
-
- case state1: /* data are stored in process_var array */
- /* memcpy(&(process_var.data), &m->data, (*m).len); */
- /* Ce memcpy devrait être portable. */
- for ( i = 0 ; i < m->len ; i++)
- d->process_var.data[i] = m->data[i];
- d->process_var.count = (*m).len;
-
- status = state2;
- break;
-
- case state2:
- /* get CobId of the dictionary correspondant to the received PDO */
- pwCobId = d->objdict[offsetObjdict].pSubindex[1].pObject;
- /* check the CobId coherance */
- /*pwCobId is the cobId read in the dictionary at the state 3 */
- if ( *pwCobId == (*m).cob_id.w ){
- /* The cobId is recognized */
- status = state4;
- MSG_WAR(0x3936, "cobId found at index ", 0x1400 + numPdo);
- break;
- }
- else {
- /* cobId received does not match with those write in the dictionnary */
- numPdo++;
- offsetObjdict++;
- status = state2;
- break;
- }
-
- case state4: /* get mapped objects number */
- /* The cobId of the message received has been found in the dictionnary. */
- offsetObjdict = d->firstIndex->PDO_RCV_MAP;
- lastIndex = d->lastIndex->PDO_RCV_MAP;
- pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
- numMap = 0;
- while (numMap < *pMappingCount) {
- UNS8 tmp[]= {0,0,0,0,0,0,0,0};
- UNS8 ByteSize;
- pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
- if (pMappingParameter == NULL) {
- MSG_ERR(0x1937, "Couldn't get mapping parameter : ", numMap + 1);
- return 0xFF;
- }
- /* Get the addresse of the mapped variable. */
- /* detail of *pMappingParameter : */
- /* The 16 hight bits contains the index, the medium 8 bits contains the subindex, */
- /* and the lower 8 bits contains the size of the mapped variable. */
-
- Size = (UNS8)(*pMappingParameter);
-
- /* copy bit per bit in little endian */
- CopyBits(Size, (UNS8*)&d->process_var.data[offset>>3], offset%8, 0, ((UNS8*)tmp), 0, 0);
-
- ByteSize = 1 + ((Size - 1) >> 3); /*1->8 => 1 ; 9->16 => 2, ... */
-
- objDict = setODentry(d, (UNS16)((*pMappingParameter) >> 16),
- (UNS8)(((*pMappingParameter) >> 8 ) & 0xFF),
- tmp, &ByteSize, 0 );
-
- if(objDict != OD_SUCCESSFUL) {
- MSG_ERR(0x1938, "error accessing to the mapped var : ", numMap + 1);
- MSG_WAR(0x2939, " Mapped at index : ", (*pMappingParameter) >> 16);
- MSG_WAR(0x2940, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
- return 0xFF;
- }
-
- MSG_WAR(0x3942, "Variable updated with value received by PDO cobid : ", m->cob_id.w);
- MSG_WAR(0x3943, " Mapped at index : ", (*pMappingParameter) >> 16);
- MSG_WAR(0x3944, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
- /* MSG_WAR(0x3945, " data : ",*((UNS32 *)pMappedAppObject)); */
- offset += Size;
- numMap++;
- } /* end loop while on mapped variables */
-
- offset=0x00;
- numMap = 0;
- return 0;
-
- }/* end switch status */
- }/* end while */
- }/* end if Donnees */
-
-
- else if ((*m).rtr == REQUEST ){
- MSG_WAR(0x3946, "Receive a PDO request cobId : ", m->cob_id.w);
- status = state1;
- offsetObjdict = d->firstIndex->PDO_TRS;
- lastIndex = d->lastIndex->PDO_TRS;
- if(offsetObjdict) while( offsetObjdict <= lastIndex ){
- /* study of all PDO stored in the objects dictionary */
-
- switch( status ){
-
- case state1: /* check the CobId */
- /* get CobId of the dictionary which match to the received PDO */
- pwCobId = (d->objdict + offsetObjdict)->pSubindex[1].pObject;
- if ( *pwCobId == (*m).cob_id.w ) {
- status = state4;
- break;
- }
- else {
- numPdo++;
- offsetObjdict++;
- }
- status = state1;
- break;
-
-
- case state4: /* check transmission type (after request?) */
- pTransmissionType = d->objdict[offsetObjdict].pSubindex[2].pObject;
- if ( (*pTransmissionType == TRANS_RTR) || (*pTransmissionType == TRANS_RTR_SYNC ) || (*pTransmissionType == TRANS_EVENT) ) {
- status = state5;
- break;
- }
- else {
- /* The requested PDO is not to send on request. So, does nothing. */
- MSG_WAR(0x2947, "PDO is not to send on request : ", m->cob_id.w);
- return 0xFF;
- }
-
- case state5: /* get mapped objects number */
- offsetObjdict = d->firstIndex->PDO_TRS_MAP;
- lastIndex = d->lastIndex->PDO_TRS_MAP;
- pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
- numMap = 0;
- while (numMap < *pMappingCount) {
- pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
- /* Get the mapped variable */
- Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
- objDict = getODentry( d, (UNS16)((*pMappingParameter) >> (UNS8)16),
- (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & 0xFF),
- (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
- if (objDict != OD_SUCCESSFUL) {
- MSG_ERR(0x1948, "error accessing to the mapped var : ", numMap + 1);
- MSG_WAR(0x2949, " Mapped at index : ", (*pMappingParameter) >> 16);
- MSG_WAR(0x2950, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
- return 0xFF;
- }
- offset += (UNS8) (((*pMappingParameter) & 0xFF) >> 3);
- d->process_var.count = offset;
- numMap++;
-
- } /* end while */
- PDOmGR( d, *pwCobId ); /* Transmit the PDO */
- return 0;
-
- }/* end switch status */
- }/* end while */
- }/* end if Requete */
-
+ while (offsetObjdict <= lastIndex) {
+
+ switch( status ) {
+
+ case state1:/*! data are stored in process_var array */
+ /*! memcpy(&(process_var.data), &m->data, (*m).len); */
+ /*! Ce memcpy devrait etre portable */
+ for ( i = 0 ; i < m->len ; i++)
+ d->process_var.data[i] = m->data[i];
+ d->process_var.count = (*m).len;
+
+ status = state2;
+ break;
+
+ case state2:
+ /*! get CobId of the dictionary correspondant to the received
+ PDO */
+ pwCobId = d->objdict[offsetObjdict].pSubindex[1].pObject;
+ /*! check the CobId coherance */
+ /*!pwCobId is the cobId read in the dictionary at the state 3
+ */
+ if ( *pwCobId == (*m).cob_id.w ){
+ /*! The cobId is recognized */
+ status = state4;
+ MSG_WAR(0x3936, "cobId found at index ", 0x1400 + numPdo);
+ break;
+ }
+ else {
+ /*! cobId received does not match with those write in the
+ dictionnary */
+ numPdo++;
+ offsetObjdict++;
+ status = state2;
+ break;
+ }
+
+ case state4:/*! Get Mapped Objects Number */
+ /*! The cobId of the message received has been found in the
+ dictionnary. */
+ offsetObjdict = d->firstIndex->PDO_RCV_MAP;
+ lastIndex = d->lastIndex->PDO_RCV_MAP;
+ pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
+ numMap = 0;
+ while (numMap < *pMappingCount) {
+ UNS8 tmp[]= {0,0,0,0,0,0,0,0};
+ UNS8 ByteSize;
+ pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
+ if (pMappingParameter == NULL) {
+ MSG_ERR(0x1937, "Couldn't get mapping parameter : ", numMap + 1);
+ return 0xFF;
+ }
+ /*! Get the addresse of the mapped variable. */
+ /*! detail of *pMappingParameter : */
+ /*! The 16 hight bits contains the index, the medium 8 bits
+ contains the subindex, */
+ /*! and the lower 8 bits contains the size of the mapped
+ variable. */
+
+ Size = (UNS8)(*pMappingParameter);
+
+ /*! copy bit per bit in little endian */
+ CopyBits(Size, (UNS8*)&d->process_var.data[offset>>3], offset%8, 0, ((UNS8*)tmp), 0, 0);
+
+ ByteSize = 1 + ((Size - 1) >> 3); /*1->8 => 1 ; 9->16 =>
+ 2, ... */
+
+ objDict = setODentry(d, (UNS16)((*pMappingParameter) >> 16),
+ (UNS8)(((*pMappingParameter) >> 8 ) & 0xFF),
+ tmp, &ByteSize, 0 );
+
+ if(objDict != OD_SUCCESSFUL) {
+ MSG_ERR(0x1938, "error accessing to the mapped var : ", numMap + 1);
+ MSG_WAR(0x2939, " Mapped at index : ", (*pMappingParameter) >> 16);
+ MSG_WAR(0x2940, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
+ return 0xFF;
+ }
+
+ MSG_WAR(0x3942, "Variable updated with value received by PDO cobid : ", m->cob_id.w);
+ MSG_WAR(0x3943, " Mapped at index : ", (*pMappingParameter) >> 16);
+ MSG_WAR(0x3944, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
+ /*! MSG_WAR(0x3945, " data : ",*((UNS32*)pMappedAppObject)); */
+ offset += Size;
+ numMap++;
+ } /*! end loop while on mapped variables */
+
+ offset=0x00;
+ numMap = 0;
+ return 0;
+
+ }/*! end switch status*/
+ }/*! end while*/
+ }/*! end if Donnees */
+ else if ((*m).rtr == REQUEST ){
+ MSG_WAR(0x3946, "Receive a PDO request cobId : ", m->cob_id.w);
+ status = state1;
+ offsetObjdict = d->firstIndex->PDO_TRS;
+ lastIndex = d->lastIndex->PDO_TRS;
+ if(offsetObjdict) while( offsetObjdict <= lastIndex ){
+ /*! study of all PDO stored in the objects dictionary */
+
+ switch( status ){
+
+ case state1:/*! check the CobId */
+ /*! get CobId of the dictionary which match to the received PDO
+ */
+ pwCobId = (d->objdict + offsetObjdict)->pSubindex[1].pObject;
+ if ( *pwCobId == (*m).cob_id.w ) {
+ status = state4;
+ break;
+ }
+ else {
+ numPdo++;
+ offsetObjdict++;
+ }
+ status = state1;
+ break;
+
+
+ case state4:/*! check transmission type (after request?) */
+ pTransmissionType = d->objdict[offsetObjdict].pSubindex[2].pObject;
+ if ( (*pTransmissionType == TRANS_RTR) || (*pTransmissionType == TRANS_RTR_SYNC ) || (*pTransmissionType == TRANS_EVENT) ) {
+ status = state5;
+ break;
+ }
+ else {
+ /*! The requested PDO is not to send on request. So, does
+ nothing. */
+ MSG_WAR(0x2947, "PDO is not to send on request : ", m->cob_id.w);
+ return 0xFF;
+ }
+
+ case state5:/*! get mapped objects number */
+ offsetObjdict = d->firstIndex->PDO_TRS_MAP;
+ lastIndex = d->lastIndex->PDO_TRS_MAP;
+ pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
+ numMap = 0;
+ while (numMap < *pMappingCount) {
+ pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
+ /*! Get the mapped variable */
+ Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
+ objDict = getODentry( d, (UNS16)((*pMappingParameter) >> (UNS8)16),
+ (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & 0xFF),
+ (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
+ if (objDict != OD_SUCCESSFUL) {
+ MSG_ERR(0x1948, "error accessing to the mapped var : ", numMap + 1);
+ MSG_WAR(0x2949, " Mapped at index : ", (*pMappingParameter) >> 16);
+ MSG_WAR(0x2950, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
+ return 0xFF;
+ }
+ offset += (UNS8) (((*pMappingParameter) & 0xFF) >> 3);
+ d->process_var.count = offset;
+ numMap++;
+
+ } /*! end while */
+ PDOmGR( d, *pwCobId ); /*! Transmit the PDO */
+ return 0;
+
+ }/*! end switch status */
+ }/*! end while */
+ }/*! end if Requete */
+
return 0;
}
-
+/*!
+**
+**
+** @param NbBits
+** @param SrcByteIndex
+** @param SrcBitIndex
+** @param SrcBigEndian
+** @param DestByteIndex
+** @param DestBitIndex
+** @param DestBigEndian
+**/
void CopyBits(UNS8 NbBits, UNS8* SrcByteIndex, UNS8 SrcBitIndex, UNS8 SrcBigEndian, UNS8* DestByteIndex, UNS8 DestBitIndex, UNS8 DestBigEndian)
{
- //This loop copy as many bits that it can each time, crossing successively bytes
- // boundaries from LSB to MSB.
- while(NbBits > 0)
- {
- // Bit missalignement between src and dest
- INTEGER8 Vect = DestBitIndex - SrcBitIndex;
-
- // We can now get src and align it to dest
- UNS8 Aligned = Vect>0 ? *SrcByteIndex << Vect : *SrcByteIndex >> -Vect;
-
- // Compute the nb of bit we will be able to copy
- UNS8 BoudaryLimit = (Vect>0 ? 8 - DestBitIndex : 8 - SrcBitIndex );
- UNS8 BitsToCopy = BoudaryLimit > NbBits ? NbBits : BoudaryLimit;
-
- // Create a mask that will serve in:
- UNS8 Mask = ((0xff << (DestBitIndex + BitsToCopy)) | (0xff >> (8 - DestBitIndex)));
-
- // - Filtering src
- UNS8 Filtered = Aligned & ~Mask;
-
- // - and erase bits where we write, preserve where we don't
- *DestByteIndex &= Mask;
-
- // Then write.
- *DestByteIndex |= Filtered ;
-
- //Compute next time cursors for src
- if((SrcBitIndex += BitsToCopy)>7) // cross boundary ?
- {
- SrcBitIndex = 0; // First bit
- SrcByteIndex += (SrcBigEndian ? -1 : 1); // Next byte
- }
-
- //Compute next time cursors for dest
- if((DestBitIndex += BitsToCopy)>7)
- {
- DestBitIndex = 0; // First bit
- DestByteIndex += (DestBigEndian ? -1 : 1);// Next byte
- }
-
- //And decrement counter.
- NbBits -= BitsToCopy;
- }
+ /*! This loop copy as many bits that it can each time, crossing*/
+ /*! successively bytes*/
+ // boundaries from LSB to MSB.
+ while(NbBits > 0)
+ {
+ /*! Bit missalignement between src and dest*/
+ INTEGER8 Vect = DestBitIndex - SrcBitIndex;
+
+ /*! We can now get src and align it to dest*/
+ UNS8 Aligned = Vect>0 ? *SrcByteIndex << Vect : *SrcByteIndex >> -Vect;
+
+ /*! Compute the nb of bit we will be able to copy*/
+ UNS8 BoudaryLimit = (Vect>0 ? 8 - DestBitIndex : 8 - SrcBitIndex );
+ UNS8 BitsToCopy = BoudaryLimit > NbBits ? NbBits : BoudaryLimit;
+
+ /*! Create a mask that will serve in:*/
+ UNS8 Mask = ((0xff << (DestBitIndex + BitsToCopy)) | (0xff >> (8 - DestBitIndex)));
+
+ /*! - Filtering src*/
+ UNS8 Filtered = Aligned & ~Mask;
+
+ /*! - and erase bits where we write, preserve where we don't*/
+ *DestByteIndex &= Mask;
+
+ /*! Then write.*/
+ *DestByteIndex |= Filtered ;
+
+ /*!Compute next time cursors for src*/
+ if((SrcBitIndex += BitsToCopy)>7)/*! cross boundary ?*/
+ {
+ SrcBitIndex = 0;/*! First bit*/
+ SrcByteIndex += (SrcBigEndian ? -1 : 1);/*! Next byte*/
+ }
+
+
+ /*!Compute next time cursors for dest*/
+ if((DestBitIndex += BitsToCopy)>7)
+ {
+ DestBitIndex = 0;/*! First bit*/
+ DestByteIndex += (DestBigEndian ? -1 : 1);/*! Next byte*/
+ }
+
+ /*!And decrement counter.*/
+ NbBits -= BitsToCopy;
+ }
}
#if 0
/*********************************************************************/
-/* TODO : reimplement this using CallBacks */
+/* TODO : reimplement this using CallBacks
+ */
/*********************************************************************/
+/*!
+**
+**
+** @param d
+** @param variable
+**
+** @return
+**/
UNS8 sendPDOevent( CO_Data* d, void * variable )
-{ /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
+{ /*! DO NOT USE MSG_ERR because the macro may send a PDO -> infinite
+ loop if it fails.*/
UNS32 objDict = 0;
UNS8 ind, sub_ind;
- UNS8 status;
+ UNS8 status;
UNS8 offset;
UNS8 * pMappingCount = NULL;
UNS32 * pMappingParameter = NULL;
void * pMappedAppObject = NULL;
- UNS8 * pTransmissionType = NULL; /* pointer to the transmission type */
+ UNS8 * pTransmissionType = NULL; /*! pointer to the transmission
+ type */
UNS32 * pwCobId = NULL;
UNS8 * pSize;
UNS8 size;
@@ -446,68 +513,72 @@
UNS16 lastIndex;
UNS8 numMap;
ind = 0x00;
- sub_ind = 1;
+ sub_ind = 1;
offset = 0x00;
pSize = &size;
status = state1;
- /* look for the index and subindex where the variable is mapped */
- /* Then, send the pdo which contains the variable. */
+
+ /*! look for the index and subindex where the variable is mapped */
+ /*! Then, send the pdo which contains the variable. */
MSG_WAR (0x3960, "sendPDOevent", 0);
offsetObjdictPrm = d->firstIndex->PDO_TRS;
-
+
offsetObjdict = d->firstIndex->PDO_TRS_MAP;
lastIndex = d->lastIndex->PDO_TRS_MAP;
- if (offsetObjdictPrm && offsetObjdict)
- /* Loop on PDO Transmit */
- while(offsetObjdict <= lastIndex){
- /* Check the transmission mode */
- pTransmissionType = d->objdict[offsetObjdictPrm].pSubindex[2].pObject;
- if (*pTransmissionType != TRANS_EVENT) {
- ind++;
- offsetObjdict++;
- offsetObjdictPrm++;
- continue;
- }
- pMappingCount = d->objdict[offsetObjdict].pSubindex[0].pObject;
- numMap = 1; /* mapped variable */
- while (numMap <= *pMappingCount) {
- pMappingParameter = d->objdict[offsetObjdict].pSubindex[numMap].pObject;
- /* Get the variable */
- objDict = getODentry( d,
- (UNS16)((*pMappingParameter) >> 16),
- (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF),
- (void * *)&pMappedAppObject, pSize, &dataType, 0 );
- if( objDict != OD_SUCCESSFUL ) {
- MSG_WAR(0x2961, "Error in dict. at index : ",
- (*pMappingParameter) >> (UNS8)16);
-
- MSG_WAR(0x2962, " subindex : ",
- ((*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF);
- return 0xFF;
- }
- if (pMappedAppObject == variable) { // Variable found !
- MSG_WAR(0x3963, "Variable to send found at index : ",
- (*pMappingParameter) >> 16);
- MSG_WAR(0x3964, " subIndex : ",
- ((*pMappingParameter) >> 8 ) & 0x000000FF);
- buildPDO(d, 0x1800 + ind);
- /* Get the cobId */
- pwCobId = d->objdict[offsetObjdictPrm].pSubindex[1].pObject;
- PDOmGR( d, *pwCobId ); /* Send the PDO */
- return 0;
- }
- numMap++;
- } /* End loop on mapped variable */
- ind++;
- offsetObjdict++;
- offsetObjdictPrm++;
- } /* End loop while on PDO */
+ if (offsetObjdictPrm && offsetObjdict)
+ /*! Loop on PDO Transmit */
+ while(offsetObjdict <= lastIndex){
+ /*! Check the transmission mode */
+ pTransmissionType = d->objdict[offsetObjdictPrm].pSubindex[2].pObject;
+ if (*pTransmissionType != TRANS_EVENT) {
+ ind++;
+ offsetObjdict++;
+ offsetObjdictPrm++;
+ continue;
+ }
+ pMappingCount = d->objdict[offsetObjdict].pSubindex[0].pObject;
+ numMap = 1; /*! mapped variable */
+ while (numMap <= *pMappingCount) {
+ pMappingParameter = d->objdict[offsetObjdict].pSubindex[numMap].pObject;
+ /*! Get the variable */
+ objDict = getODentry( d,
+ (UNS16)((*pMappingParameter) >> 16),
+ (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF),
+ (void * *)&pMappedAppObject, pSize, &dataType, 0 );
+ if( objDict != OD_SUCCESSFUL ) {
+ MSG_WAR(0x2961, "Error in dict. at index : ",
+ (*pMappingParameter) >> (UNS8)16);
+
+ MSG_WAR(0x2962, " subindex : ",
+ ((*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF);
+ return 0xFF;
+ }
+ if (pMappedAppObject == variable) { // Variable found !
+ MSG_WAR(0x3963, "Variable to send found at index : ",
+ (*pMappingParameter) >> 16);
+ MSG_WAR(0x3964, " subIndex : ",
+ ((*pMappingParameter) >> 8 ) & 0x000000FF);
+ buildPDO(d, 0x1800 + ind);
+ /*! Get the cobId */
+ pwCobId = d->objdict[offsetObjdictPrm].pSubindex[1].pObject;
+ PDOmGR( d, *pwCobId ); /*! Send the PDO */
+ return 0;
+ }
+ numMap++;
+ } /*! End loop on mapped variable */
+ ind++;
+ offsetObjdict++;
+ offsetObjdictPrm++;
+ } /*! End loop while on PDO */
MSG_WAR(0x2965, "Variable not found in a PDO to send on event", 0);
return 0xFF;
}
#endif
+
+
+
--- a/src/sdo.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/sdo.c Tue Jun 05 16:41:38 2007 +0200
@@ -19,6 +19,15 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*!
+** @file sdo.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
/* #define DEBUG_WAR_CONSOLE_ON */
/* #define DEBUG_ERR_CONSOLE_ON */
@@ -38,11 +47,36 @@
/*Internals prototypes*/
-/** Called by writeNetworkDict */
+/*!
+** Called by writeNetworkDict
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+** @param endianize
+**
+** @return
+**/
INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
-/** Called by readNetworkDict */
+/*!
+** Called by readNetworkDict
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+** @param Callback
+**
+** @return
+**/
INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
UNS8 dataType, SDOCallback_t Callback);
@@ -84,12 +118,14 @@
/** Returns the subIndex from the byte 3 of the SDO
*/
-
#define getSDOsubIndex(byte3) (byte3)
-/***************************************************************************
-**
-*/
+/*!
+**
+**
+** @param d
+** @param id
+**/
void SDOTimeoutAlarm(CO_Data* d, UNS32 id)
{
MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
@@ -125,19 +161,28 @@
MSG_WAR(0x3A07, "restartSDO_TIMER for line : ", line);\
if(d->transfers[id].timer != TIMER_NONE) { StopSDO_TIMER(id) StartSDO_TIMER(id) }
-/***************************************************************************/
-/** Reset all sdo buffers
- */
+/*!
+** Reset all sdo buffers
+**
+** @param d
+**/
void resetSDO (CO_Data* d)
{
UNS8 j;
- /* transfer structure initialization */
+ /** transfer structure initialization */
for (j = 0 ; j < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; j++)
resetSDOline(d, j);
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+**
+** @return
+**/
UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line)
{
UNS8 size;
@@ -153,7 +198,14 @@
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+**
+** @return
+**/
UNS32 objdictToSDOline (CO_Data* d, UNS8 line)
{
UNS8 size = 0;
@@ -174,7 +226,7 @@
d->transfers[line].count = size;
d->transfers[line].offset = 0;
#if 0
- /*Me laisser ça, please ! (FD)*/
+ /*Me laisser a, please ! (FD)*/
{
UNS8 i;
for (i = 0 ; i < 10 ; i++) {
@@ -185,7 +237,16 @@
return 0;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+** @param data
+**
+** @return
+**/
UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8* data) {
UNS8 i;
UNS8 offset;
@@ -205,8 +266,16 @@
return 0;
}
-
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+** @param data
+**
+** @return
+**/
UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8* data)
{
UNS8 i;
@@ -223,7 +292,18 @@
return 0;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param whoami
+** @param index
+** @param subIndex
+** @param abortCode
+**
+** @return
+**/
UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index,
UNS8 subIndex, UNS32 abortCode)
{
@@ -249,7 +329,12 @@
return 0;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+**/
void resetSDOline ( CO_Data* d, UNS8 line )
{
UNS8 i;
@@ -259,7 +344,18 @@
d->transfers[line].data[i] = 0;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+** @param nodeId
+** @param index
+** @param subIndex
+** @param state
+**
+** @return
+**/
UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
{
MSG_WAR(0x3A25, "init SDO line nb : ", line);
@@ -280,7 +376,15 @@
return 0;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param whoami
+** @param line
+**
+** @return
+**/
UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
{
@@ -297,7 +401,16 @@
return 0xFF;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param whoami
+** @param line
+**
+** @return
+**/
UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
{
@@ -314,7 +427,15 @@
return 0xFF;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param whoami
+**
+** @return
+**/
UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
{
UNS8 err;
@@ -328,7 +449,15 @@
return 0;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+**
+** @return
+**/
UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 * nbBytes)
{
if (d->transfers[line].count == 0) /* if received initiate SDO protocol with e=0 and s=0 */
@@ -338,7 +467,15 @@
return 0;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+**
+** @return
+**/
UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 nbBytes)
{
if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
@@ -349,8 +486,15 @@
return 0;
}
-
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param whoami
+** @param sdo
+**
+** @return
+**/
UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
{
UNS16 offset;
@@ -367,8 +511,8 @@
return 0xFF;
}
- /*get the server->client cobid*/
- if ( whoami == SDO_SERVER ) {/*case server. Easy because today only one server SDO is authorized in CanFestival*/
+ /**get the server->client cobid*/
+ if ( whoami == SDO_SERVER ) {/**case server. Easy because today only one server SDO is authorized in CanFestival*/
offset = d->firstIndex->SDO_SVR;
if (offset == 0) {
MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0);
@@ -377,8 +521,8 @@
pwCobId = d->objdict[offset].pSubindex[2].pObject;
MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId);
}
- else { /*case client*/
- /* Get the client->server cobid.*/
+ else { /**case client*/
+ /** Get the client->server cobid.*/
UNS16 sdoNum = 0;
offset = d->firstIndex->SDO_CLT;
lastIndex = d->lastIndex->SDO_CLT;
@@ -386,7 +530,7 @@
MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0);
return 0xFF;
}
- /* First, have to find at the index where is defined the communication with the server node */
+ /** First, have to find at the index where is defined the communication with the server node */
while (offset <= lastIndex){
MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
if (d->objdict[offset].bSubCount <= 3) {
@@ -406,13 +550,13 @@
MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
return 0xFF;
}
- /* Second, read the cobid client->server */
+ /** Second, read the cobid client->server */
pwCobId = d->objdict[offset].pSubindex[1].pObject;
}
- /* message copy for sending */
+ /** message copy for sending */
m.cob_id.w = *pwCobId;
m.rtr = NOT_A_REQUEST;
- /* the length of SDO must be 8 */
+ /** the length of SDO must be 8 */
m.len = 8;
for (i = 0 ; i < 8 ; i++) {
m.data[i] = sdo.body.data[i];
@@ -420,7 +564,17 @@
return canSend(d->canHandle,&m);
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param whoami
+** @param index
+** @param subIndex
+** @param abortCode
+**
+** @return
+**/
UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode)
{
s_SDO sdo;
@@ -443,18 +597,25 @@
return ret;
}
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param m
+**
+** @return
+**/
UNS8 proceedSDO (CO_Data* d, Message *m)
{
UNS8 err;
UNS8 line;
- UNS8 nbBytes; /* received or to be transmited. */
- UNS8 nodeId = 0; /* The node from which the SDO is received */
- UNS32 nodeId_32; /* node id in 32 bits, for temporary use */
+ UNS8 nbBytes; /** received or to be transmited. */
+ UNS8 nodeId = 0; /** The node from which the SDO is received */
+ UNS32 nodeId_32; /** node id in 32 bits, for temporary use */
UNS32 *pNodeId = NULL;
- UNS8 whoami = SDO_UNKNOWN; /* SDO_SERVER or SDO_CLIENT.*/
- UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
- s_SDO sdo; /* SDO to transmit */
+ UNS8 whoami = SDO_UNKNOWN; /** SDO_SERVER or SDO_CLIENT.*/
+ UNS32 errorCode; /** while reading or writing in the local object dictionary.*/
+ s_SDO sdo; /** SDO to transmit */
UNS16 index;
UNS8 subIndex;
UNS32 abortCode;
@@ -465,8 +626,8 @@
MSG_WAR(0x3A60, "proceedSDO ", 0);
whoami = SDO_UNKNOWN;
- /* Looking for the cobId in the object dictionary. */
- /* Am-I a server ? */
+ /** Looking for the cobId in the object dictionary. */
+ /** Am-I a server ? */
offset = d->firstIndex->SDO_SVR;
lastIndex = d->lastIndex->SDO_SVR;
j = 0;
@@ -479,16 +640,16 @@
if ( *pCobId == (*m).cob_id.w ) {
whoami = SDO_SERVER;
MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
- /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
- /* 0x1200 where the cobid received is defined. */
+ /** In case of server, the node id of the client may be unknown. So we put the index minus offset */
+ /** 0x1200 where the cobid received is defined. */
nodeId = j;
break;
}
j++;
offset++;
- } /* end while */
+ } /** end while */
if (whoami == SDO_UNKNOWN) {
- /* Am-I client ? */
+ /** Am-I client ? */
offset = d->firstIndex->SDO_CLT;
lastIndex = d->lastIndex->SDO_CLT;
j = 0;
@@ -497,10 +658,10 @@
MSG_ERR(0x1A63, "Subindex 3 not found at index ", 0x1280 + j);
return 0xFF;
}
- /* a) Looking for the cobid received. */
+ /** a) Looking for the cobid received. */
pCobId = d->objdict[offset].pSubindex[2].pObject;
if (*pCobId == (*m).cob_id.w ) {
- /* b) cobid found, so reading the node id of the server. */
+ /** b) cobid found, so reading the node id of the server. */
pNodeId = d->objdict[offset].pSubindex[3].pObject;
whoami = SDO_CLIENT;
nodeId_32 = *pNodeId;
@@ -514,10 +675,10 @@
} /* end while */
}
if (whoami == SDO_UNKNOWN) {
- return 0xFF;/* This SDO was not for us ! */
- }
-
- /* Test if the size of the SDO is ok */
+ return 0xFF;/** This SDO was not for us ! */
+ }
+
+ /** Test if the size of the SDO is ok */
if ( (*m).len != 8) {
MSG_ERR(0x1A67, "Error size SDO. CobId : ", (*m).cob_id.w);
failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
@@ -531,16 +692,16 @@
MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", (*m).cob_id.w);
}
- /* Testing the command specifier */
- /* Allowed : cs = 0, 1, 2, 3, 4. (= all except those for block tranfert). */
- /* cs = other : Not allowed -> abort. */
+ /** Testing the command specifier */
+ /** Allowed : cs = 0, 1, 2, 3, 4. (= all except those for block tranfert). */
+ /** cs = other : Not allowed -> abort. */
switch (getSDOcs(m->data[0])) {
case 0:
- /* I am SERVER */
+ /** I am SERVER */
if (whoami == SDO_SERVER) {
- /* Receiving a download segment data. */
- /* A SDO transfert should have been yet initiated. */
+ /** Receiving a download segment data. */
+ /** A SDO transfert should have been yet initiated. */
err = getSDOlineOnUse( d, nodeId, whoami, &line );
if (!err)
err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
@@ -550,52 +711,52 @@
failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* Reset the wathdog */
+ /** Reset the wathdog */
RestartSDO_TIMER(line)
MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId);
index = d->transfers[line].index;
subIndex = d->transfers[line].subIndex;
- /* Toggle test. */
+ /** Toggle test. */
if (d->transfers[line].toggle != getSDOt(m->data[0])) {
MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
return 0xFF;
}
- /* Nb of data to be downloaded */
+ /** Nb of data to be downloaded */
nbBytes = 7 - getSDOn3(m->data[0]);
- /* Store the data in the transfert structure. */
+ /** Store the data in the transfert structure. */
err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
if (err) {
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
return 0xFF;
}
- /* Sending the SDO response, CS = 1 */
- sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
+ /** Sending the SDO response, CS = 1 */
+ sdo.nodeId = *d->bDeviceNodeId; /** The node id of the server, (here it is the sender). */
sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
for (i = 1 ; i < 8 ; i++)
sdo.body.data[i] = 0;
MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId);
sendSDO(d, whoami, sdo);
- /* Inverting the toggle for the next segment. */
+ /** Inverting the toggle for the next segment. */
d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
- /* If it was the last segment, */
+ /** If it was the last segment, */
if (getSDOc(m->data[0])) {
- /* Transfering line data to object dictionary. */
- /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
+ /** Transfering line data to object dictionary. */
+ /** The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
errorCode = SDOlineToObjdict(d, line);
if (errorCode) {
MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);
failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
return 0xFF;
}
- /* Release of the line */
+ /** Release of the line */
resetSDOline(d, line);
MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId);
}
} /* end if SERVER */
else { /* if CLIENT */
- /* I am CLIENT */
- /* It is a request for a previous upload segment. We should find a line opened for this.*/
+ /** I am CLIENT */
+ /** It is a request for a previous upload segment. We should find a line opened for this.*/
err = getSDOlineOnUse( d, nodeId, whoami, &line);
if (!err)
err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
@@ -604,38 +765,38 @@
failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* Reset the wathdog */
+ /** Reset the wathdog */
RestartSDO_TIMER(line)
index = d->transfers[line].index;
subIndex = d->transfers[line].subIndex;
- /* test of the toggle; */
+ /** test of the toggle; */
if (d->transfers[line].toggle != getSDOt(m->data[0])) {
MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
return 0xFF;
}
- /* nb of data to be uploaded */
+ /** nb of data to be uploaded */
nbBytes = 7 - getSDOn3(m->data[0]);
- /* Storing the data in the line structure. */
+ /** Storing the data in the line structure. */
err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
if (err) {
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
return 0xFF;
}
- /* Inverting the toggle for the next segment. */
+ /** Inverting the toggle for the next segment. */
d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
- /* If it was the last segment,*/
+ /** If it was the last segment,*/
if ( getSDOc(m->data[0])) {
- /* Put in state finished */
- /* The code is safe for the case e=s=0 in initiate frame. */
+ /** Put in state finished */
+ /** The code is safe for the case e=s=0 in initiate frame. */
StopSDO_TIMER(line)
d->transfers[line].state = SDO_FINISHED;
if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
}
- else { /* more segments to receive */
- /* Sending the request for the next segment. */
+ else { /** more segments to receive */
+ /** Sending the request for the next segment. */
sdo.nodeId = nodeId;
sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
for (i = 1 ; i < 8 ; i++)
@@ -647,8 +808,8 @@
break;
case 1:
- /* I am SERVER */
- /* Receive of an initiate download */
+ /** I am SERVER */
+ /** Receive of an initiate download */
if (whoami == SDO_SERVER) {
index = getSDOindex(m->data[1],m->data[2]);
subIndex = getSDOsubIndex(m->data[3]);
@@ -657,15 +818,15 @@
MSG_WAR(0x3A80, "Writing at index : ", index);
MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
- /* Search if a SDO transfert have been yet initiated */
+ /** Search if a SDO transfert have been yet initiated */
err = getSDOlineOnUse( d, nodeId, whoami, &line );
if (! err) {
MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* No line on use. Great ! */
- /* Try to open a new line. */
+ /** No line on use. Great ! */
+ /** Try to open a new line. */
err = getSDOfreeLine( d, whoami, &line );
if (err) {
MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
@@ -674,10 +835,10 @@
}
initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
- if (getSDOe(m->data[0])) { /* If SDO expedited */
- /* nb of data to be downloaded */
+ if (getSDOe(m->data[0])) { /** If SDO expedited */
+ /** nb of data to be downloaded */
nbBytes = 4 - getSDOn2(m->data[0]);
- /* Storing the data in the line structure. */
+ /** Storing the data in the line structure. */
d->transfers[line].count = nbBytes;
err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
@@ -686,23 +847,23 @@
return 0xFF;
}
- /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
- /* The line will be reseted when it is downloading in the dictionary. */
+ /** SDO expedited -> transfert finished. Data can be stored in the dictionary. */
+ /**The line will be reseted when it is downloading in the dictionary. */
MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
- /* Transfering line data to object dictionary. */
+ /** Transfering line data to object dictionary. */
errorCode = SDOlineToObjdict(d, line);
if (errorCode) {
MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);
failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
return 0xFF;
}
- /* Release of the line. */
+ /** Release of the line. */
resetSDOline(d, line);
}
- else {/* So, if it is not an expedited transfert */
+ else {/** So, if it is not an expedited transfert */
if (getSDOs(m->data[0])) {
- /* TODO : if e and s = 0, not reading m->data[4] but put nbBytes = 0 */
- nbBytes = m->data[4]; /* Transfert limited to 255 bytes. */
+ /** TODO : if e and s = 0, not reading m->data[4] but put nbBytes = 0 */
+ nbBytes = m->data[4]; /** Transfert limited to 255 bytes. */
err = setSDOlineRestBytes(d, nodeId, nbBytes);
if (err) {
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
@@ -710,8 +871,8 @@
}
}
}
- /*Sending a SDO, cs=3*/
- sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
+ /**Sending a SDO, cs=3*/
+ sdo.nodeId = *d->bDeviceNodeId; /** The node id of the server, (here it is the sender).*/
sdo.body.data[0] = 3 << 5;
sdo.body.data[1] = index & 0xFF; /* LSB */
sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
@@ -721,8 +882,8 @@
sendSDO(d, whoami, sdo);
} /* end if I am SERVER */
else {
- /* I am CLIENT */
- /* It is a response for a previous download segment. We should find a line opened for this. */
+ /** I am CLIENT */
+ /** It is a response for a previous download segment. We should find a line opened for this. */
err = getSDOlineOnUse( d, nodeId, whoami, &line);
if (!err)
err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
@@ -731,18 +892,18 @@
failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* Reset the wathdog */
+ /** Reset the wathdog */
RestartSDO_TIMER(line)
index = d->transfers[line].index;
subIndex = d->transfers[line].subIndex;
- /* test of the toggle; */
+ /** test of the toggle; */
if (d->transfers[line].toggle != getSDOt(m->data[0])) {
MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
return 0xFF;
}
- /* End transmission or downloading next segment. We need to know if it will be the last one. */
+ /** End transmission or downloading next segment. We need to know if it will be the last one. */
getSDOlineRestBytes(d, line, &nbBytes);
if (nbBytes == 0) {
MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);
@@ -751,10 +912,10 @@
if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
return 0x00;
}
- /* At least one transfer to send. */
+ /** At least one transfer to send. */
if (nbBytes > 7) {
- /* several segments to download.*/
- /* code to send the next segment. (cs = 0; c = 0) */
+ /** several segments to download.*/
+ /** code to send the next segment. (cs = 0; c = 0) */
d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
sdo.nodeId = nodeId; /* The server node Id; */
sdo.body.data[0] = (d->transfers[line].toggle << 4);
@@ -765,8 +926,8 @@
}
}
else {
- /* Last segment. */
- /* code to send the last segment. (cs = 0; c = 1)*/
+ /** Last segment. */
+ /** code to send the last segment. (cs = 0; c = 1)*/
d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
sdo.nodeId = nodeId; /* The server node Id; */
sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
@@ -780,12 +941,12 @@
}
MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);
sendSDO(d, whoami, sdo);
- } /* end if I am a CLIENT */
+ } /** end if I am a CLIENT */
break;
case 2:
- /* I am SERVER */
- /* Receive of an initiate upload.*/
+ /** I am SERVER */
+ /** Receive of an initiate upload.*/
if (whoami == SDO_SERVER) {
index = getSDOindex(m->data[1],m->data[2]);
subIndex = getSDOsubIndex(m->data[3]);
@@ -793,7 +954,7 @@
nodeId);
MSG_WAR(0x3A90, "Reading at index : ", index);
MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
- /* Search if a SDO transfert have been yet initiated*/
+ /** Search if a SDO transfert have been yet initiated*/
err = getSDOlineOnUse( d, nodeId, whoami, &line );
if (! err) {
MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
@@ -801,8 +962,8 @@
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* No line on use. Great !*/
- /* Try to open a new line.*/
+ /** No line on use. Great !*/
+ /** Try to open a new line.*/
err = getSDOfreeLine( d, whoami, &line );
if (err) {
MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
@@ -810,7 +971,7 @@
return 0xFF;
}
initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
- /* Transfer data from dictionary to the line structure. */
+ /** Transfer data from dictionary to the line structure. */
errorCode = objdictToSDOline(d, line);
if (errorCode) {
@@ -819,26 +980,26 @@
failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
return 0xFF;
}
- /* Preparing the response.*/
- getSDOlineRestBytes(d, line, &nbBytes); /* Nb bytes to transfer ? */
- sdo.nodeId = nodeId; /* The server node Id; */
+ /** Preparing the response.*/
+ getSDOlineRestBytes(d, line, &nbBytes); /** Nb bytes to transfer ? */
+ sdo.nodeId = nodeId; /** The server node Id; */
if (nbBytes > 4) {
- /* normal transfert. (segmented). */
- /* code to send the initiate upload response. (cs = 2) */
+ /** normal transfert. (segmented). */
+ /** code to send the initiate upload response. (cs = 2) */
sdo.body.data[0] = (2 << 5) | 1;
sdo.body.data[1] = index & 0xFF; /* LSB */
sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
sdo.body.data[3] = subIndex;
sdo.body.data[4] = nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
- /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
- /* in the object dictionary, at every index and subindex. */
+ /** It takes too much memory to upgrate to 2^32 because the size of data is also coded */
+ /** in the object dictionary, at every index and subindex. */
for (i = 5 ; i < 8 ; i++)
sdo.body.data[i] = 0;
MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
sendSDO(d, whoami, sdo);
}
else {
- /* Expedited upload. (cs = 2 ; e = 1) */
+ /** Expedited upload. (cs = 2 ; e = 1) */
sdo.body.data[0] = (2 << 5) | ((4 - nbBytes) << 2) | 3;
sdo.body.data[1] = index & 0xFF; /* LSB */
sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
@@ -853,14 +1014,14 @@
MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
nodeId);
sendSDO(d, whoami, sdo);
- /* Release the line.*/
+ /** Release the line.*/
resetSDOline(d, line);
}
- } /* end if I am SERVER*/
+ } /** end if I am SERVER*/
else {
- /* I am CLIENT */
- /* It is the response for the previous initiate upload request.*/
- /* We should find a line opened for this. */
+ /** I am CLIENT */
+ /** It is the response for the previous initiate upload request.*/
+ /** We should find a line opened for this. */
err = getSDOlineOnUse( d, nodeId, whoami, &line);
if (!err)
err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
@@ -869,21 +1030,21 @@
failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* Reset the wathdog */
+ /** Reset the wathdog */
RestartSDO_TIMER(line)
index = d->transfers[line].index;
subIndex = d->transfers[line].subIndex;
if (getSDOe(m->data[0])) { /* If SDO expedited */
- /* nb of data to be uploaded */
+ /** nb of data to be uploaded */
nbBytes = 4 - getSDOn2(m->data[0]);
- /* Storing the data in the line structure. */
+ /** Storing the data in the line structure. */
err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
if (err) {
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
return 0xFF;
}
- /* SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
+ /** SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
StopSDO_TIMER(line)
d->transfers[line].count = nbBytes;
@@ -891,17 +1052,17 @@
if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
return 0;
}
- else { /* So, if it is not an expedited transfert */
- /* Storing the nb of data to receive. */
+ else { /** So, if it is not an expedited transfert */
+ /** Storing the nb of data to receive. */
if (getSDOs(m->data[0])) {
- nbBytes = m->data[4]; /* Remember the limitation to 255 bytes to transfert */
+ nbBytes = m->data[4]; /** Remember the limitation to 255 bytes to transfert */
err = setSDOlineRestBytes(d, line, nbBytes);
if (err) {
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
return 0xFF;
}
}
- /* Requesting next segment. (cs = 3) */
+ /** Requesting next segment. (cs = 3) */
sdo.nodeId = nodeId;
sdo.body.data[0] = 3 << 5;
for (i = 1 ; i < 8 ; i++)
@@ -909,14 +1070,14 @@
MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
sendSDO(d, whoami, sdo);
}
- } /* End if CLIENT */
+ } /** End if CLIENT */
break;
case 3:
- /* I am SERVER */
+ /** I am SERVER */
if (whoami == SDO_SERVER) {
- /* Receiving a upload segment. */
- /* A SDO transfert should have been yet initiated. */
+ /** Receiving a upload segment. */
+ /** A SDO transfert should have been yet initiated. */
err = getSDOlineOnUse( d, nodeId, whoami, &line );
if (!err)
err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
@@ -926,22 +1087,22 @@
failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* Reset the wathdog */
+ /** Reset the wathdog */
RestartSDO_TIMER(line)
MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId);
index = d->transfers[line].index;
subIndex = d->transfers[line].subIndex;
- /* Toggle test.*/
+ /** Toggle test.*/
if (d->transfers[line].toggle != getSDOt(m->data[0])) {
MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
return 0xFF;
}
- /* Uploading next segment. We need to know if it will be the last one. */
+ /** Uploading next segment. We need to know if it will be the last one. */
getSDOlineRestBytes(d, line, &nbBytes);
if (nbBytes > 7) {
- /* The segment to transfer is not the last one.*/
- /* code to send the next segment. (cs = 0; c = 0) */
+ /** The segment to transfer is not the last one.*/
+ /** code to send the next segment. (cs = 0; c = 0) */
sdo.nodeId = nodeId; /* The server node Id; */
sdo.body.data[0] = (d->transfers[line].toggle << 4);
err = lineToSDO(d, line, 7, sdo.body.data + 1);
@@ -949,15 +1110,15 @@
failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
return 0xFF;
}
- /* Inverting the toggle for the next tranfert. */
+ /** Inverting the toggle for the next tranfert. */
d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId);
sendSDO(d, whoami, sdo);
}
else {
- /* Last segment. */
- /* code to send the last segment. (cs = 0; c = 1) */
- sdo.nodeId = nodeId; /* The server node Id; */
+ /** Last segment. */
+ /** code to send the last segment. (cs = 0; c = 1) */
+ sdo.nodeId = nodeId; /** The server node Id; */
sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
if (err) {
@@ -968,14 +1129,14 @@
sdo.body.data[i] = 0;
MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);
sendSDO(d, whoami, sdo);
- /* Release the line */
+ /** Release the line */
resetSDOline(d, line);
}
} /* end if SERVER*/
else {
- /* I am CLIENT */
- /* It is the response for the previous initiate download request. */
- /* We should find a line opened for this. */
+ /** I am CLIENT */
+ /** It is the response for the previous initiate download request. */
+ /** We should find a line opened for this. */
err = getSDOlineOnUse( d, nodeId, whoami, &line);
if (!err)
err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
@@ -984,7 +1145,7 @@
failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
return 0xFF;
}
- /* Reset the watchdog */
+ /** Reset the watchdog */
RestartSDO_TIMER(line)
index = d->transfers[line].index;
subIndex = d->transfers[line].subIndex;
@@ -998,9 +1159,9 @@
return 0x00;
}
if (nbBytes > 7) {
- /* more than one request to send */
- /* code to send the next segment. (cs = 0; c = 0) */
- sdo.nodeId = nodeId; /* The server node Id; */
+ /** more than one request to send */
+ /** code to send the next segment. (cs = 0; c = 0) */
+ sdo.nodeId = nodeId; /** The server node Id; */
sdo.body.data[0] = (d->transfers[line].toggle << 4);
err = lineToSDO(d, line, 7, sdo.body.data + 1);
if (err) {
@@ -1009,9 +1170,9 @@
}
}
else {
- /* Last segment.*/
- /* code to send the last segment. (cs = 0; c = 1) */
- sdo.nodeId = nodeId; /* The server node Id; */
+ /** Last segment.*/
+ /** code to send the last segment. (cs = 0; c = 1) */
+ sdo.nodeId = nodeId; /** The server node Id; */
sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
if (err) {
@@ -1032,8 +1193,8 @@
((UNS32)m->data[5] << 8) |
((UNS32)m->data[6] << 16) |
((UNS32)m->data[7] << 24);
- /* Received SDO abort. */
- /* Looking for the line concerned. */
+ /** Received SDO abort. */
+ /** Looking for the line concerned. */
if (whoami == SDO_SERVER) {
err = getSDOlineOnUse( d, nodeId, whoami, &line );
if (!err) {
@@ -1042,13 +1203,13 @@
}
else
MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
- /* Tips : The end user has no way to know that the server node has received an abort SDO. */
- /* Its is ok, I think.*/
+ /** Tips : The end user has no way to know that the server node has received an abort SDO. */
+ /** Its is ok, I think.*/
}
- else { /* If I am CLIENT */
+ else { /** If I am CLIENT */
err = getSDOlineOnUse( d, nodeId, whoami, &line );
if (!err) {
- /* The line *must* be released by the core program. */
+ /** The line *must* be released by the core program. */
StopSDO_TIMER(line)
d->transfers[line].state = SDO_ABORTED_RCV;
d->transfers[line].abortCode = abortCode;
@@ -1060,7 +1221,7 @@
}
break;
default:
- /* Error : Unknown cs */
+ /** Error : Unknown cs */
MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
return 0xFF;
@@ -1068,7 +1229,21 @@
return 0;
}
-/*******************************************************************)******/
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+** @param endianize
+**
+** @return
+**/
INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
{
@@ -1087,19 +1262,19 @@
MSG_WAR(0x3AC2, " subIndex : ", subIndex);
MSG_WAR(0x3AC3, " nb bytes : ", count);
- /* Verify that there is no SDO communication yet. */
+ /** Verify that there is no SDO communication yet. */
err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
if (!err) {
MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);
return 0xFF;
}
- /* Taking the line ... */
+ /** Taking the line ... */
err = getSDOfreeLine( d, SDO_CLIENT, &line );
if (err) {
MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
return (0xFF);
}
- /* Check which SDO to use to communicate with the node */
+ /** Check which SDO to use to communicate with the node */
offset = d->firstIndex->SDO_CLT;
lastIndex = d->lastIndex->SDO_CLT;
if (offset == 0) {
@@ -1112,7 +1287,7 @@
MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
return 0xFF;
}
- /* looking for the nodeId server */
+ /** looking for the nodeId server */
pNodeIdServer = d->objdict[offset].pSubindex[3].pObject;
nodeIdServer = *pNodeIdServer;
MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
@@ -1134,7 +1309,7 @@
d->transfers[line].count = count;
d->transfers[line].dataType = dataType;
- /* Copy data to transfers structure. */
+ /** Copy data to transfers structure. */
for (j = 0 ; j < count ; j++) {
# ifdef CANOPEN_BIG_ENDIAN
if (dataType == 0 && endianize)
@@ -1145,17 +1320,17 @@
d->transfers[line].data[j] = ((char *)data)[j];
# endif
}
- /* Send the SDO to the server. Initiate download, cs=1. */
+ /** Send the SDO to the server. Initiate download, cs=1. */
sdo.nodeId = nodeId;
- if (count <= 4) { /* Expedited transfert */
+ if (count <= 4) { /** Expedited transfert */
sdo.body.data[0] = (1 << 5) | ((4 - count) << 2) | 3;
for (i = 4 ; i < 8 ; i++)
sdo.body.data[i] = d->transfers[line].data[i - 4];
d->transfers[line].offset = count;
}
- else { /* Normal transfert */
+ else { /** Normal transfert */
sdo.body.data[0] = (1 << 5) | 1;
- sdo.body.data[4] = count; /* nb of byte to transmit. Max = 255. (canfestival2 limitation). */
+ sdo.body.data[4] = count; /** nb of byte to transmit. Max = 255. (canfestival2 limitation). */
for (i = 5 ; i < 8 ; i++)
sdo.body.data[i] = 0;
}
@@ -1168,7 +1343,7 @@
err = sendSDO(d, SDO_CLIENT, sdo);
if (err) {
MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
- /* release the line */
+ /** release the line */
resetSDOline(d, line);
return 0xFF;
}
@@ -1177,24 +1352,57 @@
return 0;
}
-/*--------------------------------------------------------------------------*/
-
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+**
+** @return
+**/
UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS8 count, UNS8 dataType, void *data)
{
return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
}
-/*--------------------------------------------------------------------------*/
-
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+**
+** @return
+**/
UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback)
{
return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
}
-
-/***************************************************************************/
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+** @param Callback
+**
+** @return
+**/
INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
{
UNS8 err;
@@ -1211,13 +1419,13 @@
MSG_WAR(0x3AD7, " subIndex : ", subIndex);
- /* Verify that there is no SDO communication yet. */
+ /** Verify that there is no SDO communication yet. */
err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
if (!err) {
MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
return 0xFF;
}
- /* Taking the line ... */
+ /** Taking the line ... */
err = getSDOfreeLine( d, SDO_CLIENT, &line );
if (err) {
MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
@@ -1226,7 +1434,7 @@
else
MSG_WAR(0x3AE0, "Transmission on line : ", line);
- /* Check which SDO to use to communicate with the node */
+ /** Check which SDO to use to communicate with the node */
offset = d->firstIndex->SDO_CLT;
lastIndex = d->lastIndex->SDO_CLT;
if (offset == 0) {
@@ -1239,7 +1447,7 @@
MSG_ERR(0x1AE2, "Subindex 3 not found at index ", 0x1280 + i);
return 0xFF;
}
- /* looking for the nodeId server */
+ /** looking for the nodeId server */
pNodeIdServer = d->objdict[offset].pSubindex[3].pObject;
nodeIdServer = *pNodeIdServer;
@@ -1258,7 +1466,7 @@
initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
sdo.nodeId = nodeId;
- /* Send the SDO to the server. Initiate upload, cs=2. */
+ /** Send the SDO to the server. Initiate upload, cs=2. */
d->transfers[line].dataType = dataType;
sdo.body.data[0] = (2 << 5);
sdo.body.data[1] = index & 0xFF; /* LSB */
@@ -1277,21 +1485,50 @@
return 0;
}
-/*--------------------------------------------------------------------------*/
-
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+**
+** @return
+**/
UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
{
return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
}
-/*--------------------------------------------------------------------------*/
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+** @param Callback
+**
+** @return
+**/
UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
{
return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
}
-/***************************************************************************/
-
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param data
+** @param size
+** @param abortCode
+**
+** @return
+**/
UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS8 *size,
UNS32 * abortCode)
{
@@ -1300,7 +1537,7 @@
UNS8 line;
* size = 0;
- /* Looking for the line tranfert. */
+ /** Looking for the line tranfert. */
err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
if (err) {
MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
@@ -1309,13 +1546,13 @@
if (d->transfers[line].state != SDO_FINISHED)
return d->transfers[line].state;
- /* Transfert is finished. Put the value in the data. */
+ /** Transfert is finished. Put the value in the data. */
* size = (UNS8)d->transfers[line].count;
for ( i = 0 ; i < *size ; i++) {
# ifdef CANOPEN_BIG_ENDIAN
if (d->transfers[line].dataType != visible_string)
( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
- else /* String of bytes. */
+ else /** String of bytes. */
( (char *) data)[i] = d->transfers[line].data[i];
# else
( (char *) data)[i] = d->transfers[line].data[i];
@@ -1324,15 +1561,22 @@
return SDO_FINISHED;
}
-/***************************************************************************/
-
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param abortCode
+**
+** @return
+**/
UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode)
{
UNS8 line = 0;
UNS8 err;
* abortCode = 0;
- /* Looking for the line tranfert. */
+ /** Looking for the line tranfert. */
err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
if (err) {
MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
--- a/src/states.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/states.c Tue Jun 05 16:41:38 2007 +0200
@@ -19,23 +19,49 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*!
+** @file states.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
#include "states.h"
#include "def.h"
#include "dcf.h"
#include "nmtSlave.h"
-/* Prototypes for internals functions */
+/** Prototypes for internals functions */
+/*!
+**
+**
+** @param d
+** @param newCommunicationState
+**/
void switchCommunicationState(CO_Data* d,
s_state_communication *newCommunicationState);
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+**
+** @return
+**/
e_nodeState getState(CO_Data* d)
{
return d->nodeState;
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+** @param m
+**/
void canDispatch(CO_Data* d, Message *m)
{
switch(m->cob_id.w >> 7)
@@ -44,7 +70,7 @@
if(d->CurrentCommunicationState.csSYNC)
proceedSYNC(d,m);
break;
- /* case TIME_STAMP: */
+ /** case TIME_STAMP: */
case PDO1tx:
case PDO1rx:
case PDO2tx:
@@ -84,8 +110,13 @@
FuncStop;\
}
#define None
-
-/*****************************************************************************/
+
+/*!
+**
+**
+** @param d
+** @param newCommunicationState
+**/
void switchCommunicationState(CO_Data* d, s_state_communication *newCommunicationState)
{
StartOrStop(csSDO, None, resetSDO(d))
@@ -96,7 +127,14 @@
StartOrStop(csBoot_Up, None, slaveSendBootUp(d))
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+** @param newState
+**
+** @return
+**/
UNS8 setState(CO_Data* d, e_nodeState newState)
{
UNS16 wIndex = 0x1F22;
@@ -108,11 +146,11 @@
case Initialisation:
{
s_state_communication newCommunicationState = {1, 0, 0, 0, 0, 0};
- /* This will force a second loop for the state switch */
+ /** This will force a second loop for the state switch */
d->nodeState = Initialisation;
newState = Pre_operational;
switchCommunicationState(d, &newCommunicationState);
- /* call user app related state func. */
+ /** call user app related state func. */
(*d->initialisation)();
}
@@ -170,37 +208,50 @@
default:
return 0xFF;
- }/* end switch case */
+ }/** end switch case */
}
return 0;
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+**
+** @return
+**/
UNS8 getNodeId(CO_Data* d)
{
return *d->bDeviceNodeId;
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+** @param nodeId
+**/
void setNodeId(CO_Data* d, UNS8 nodeId)
{
UNS16 offset = d->firstIndex->SDO_SVR;
if(offset){
- /* cob_id_client = 0x600 + nodeId; */
+ /** cob_id_client = 0x600 + nodeId; */
*(UNS32*)d->objdict[offset].pSubindex[1].pObject = 0x600 + nodeId;
- /* cob_id_server = 0x580 + nodeId; */
+ /** cob_id_server = 0x580 + nodeId; */
*(UNS32*)d->objdict[offset].pSubindex[2].pObject = 0x580 + nodeId;
- /* node Id client. As we do not know the value, we put the node Id Server */
- /* *(UNS8*)d->objdict[offset].pSubindex[3].pObject = nodeId; */
+ /** node Id client. As we do not know the value, we put the node Id Server */
+ /** *(UNS8*)d->objdict[offset].pSubindex[3].pObject = nodeId; */
}
- /* ** Initialize the server(s) SDO parameters */
- /* Remember that only one SDO server is allowed, defined at index 0x1200 */
-
- /* ** Initialize the client(s) SDO parameters */
- /* Nothing to initialize (no default values required by the DS 401) */
- /* ** Initialize the receive PDO communication parameters. Only for 0x1400 to 0x1403 */
+ /**
+ Initialize the server(s) SDO parameters
+ Remember that only one SDO server is allowed, defined at index 0x1200
+
+ Initialize the client(s) SDO parameters
+ Nothing to initialize (no default values required by the DS 401)
+ Initialize the receive PDO communication parameters. Only for 0x1400 to 0x1403
+ */
{
UNS8 i = 0;
UNS16 offset = d->firstIndex->PDO_RCV;
@@ -227,7 +278,7 @@
offset ++;
}
}
- /* bDeviceNodeId is defined in the object dictionary. */
+ /** bDeviceNodeId is defined in the object dictionary. */
*d->bDeviceNodeId = nodeId;
}
--- a/src/sync.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/sync.c Tue Jun 05 16:41:38 2007 +0200
@@ -20,33 +20,63 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*!
+** @file sync.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
#include "data.h"
#include "sync.h"
#include "canfestival.h"
/* Prototypes for internals functions */
+
+/*!
+**
+**
+** @param d
+** @param id
+**/
void SyncAlarm(CO_Data* d, UNS32 id);
UNS32 OnCOB_ID_SyncUpdate(CO_Data* d, const indextable * unsused_indextable,
UNS8 unsused_bSubindex);
-
-
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+** @param id
+**/
void SyncAlarm(CO_Data* d, UNS32 id)
{
sendSYNC(d, *d->COB_ID_Sync & 0x1FFFFFFF) ;
}
-/*****************************************************************************/
-/* This is called when Index 0x1005 is updated.*/
+/*!
+** This is called when Index 0x1005 is updated.
+**
+** @param d
+** @param unsused_indextable
+** @param unsused_bSubindex
+**
+** @return
+**/
UNS32 OnCOB_ID_SyncUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
{
startSYNC(d);
return 0;
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+**/
void startSYNC(CO_Data* d)
{
RegisterSetODentryCallBack(d, 0x1005, 0, &OnCOB_ID_SyncUpdate);
@@ -67,13 +97,24 @@
}
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+**/
void stopSYNC(CO_Data* d)
{
d->syncTimer = DelAlarm(d->syncTimer);
}
-/*********************************************************************/
+/*!
+**
+**
+** @param d
+** @param cob_id
+**
+** @return
+**/
UNS8 sendSYNC(CO_Data* d, UNS32 cob_id)
{
Message m;
@@ -89,7 +130,14 @@
return resultat ;
}
-/*****************************************************************************/
+/*!
+**
+**
+** @param d
+** @param m
+**
+** @return
+**/
UNS8 proceedSYNC(CO_Data* d, Message *m)
{
@@ -97,11 +145,11 @@
prp_j;
const UNS8 * pMappingCount = NULL; /* count of mapped objects...*/
- /* pointer to the var which is mapped to a pdo */
+ /** pointer to the var which is mapped to a pdo */
/* void * pMappedAppObject = NULL; */
- /* pointer fo the var which holds the mapping parameter of an mapping entry */
+ /** pointer fo the var which holds the mapping parameter of an mapping entry */
UNS32 * pMappingParameter = NULL;
- /* pointer to the transmissiontype...*/
+ /** pointer to the transmissiontype...*/
UNS8 * pTransmissionType = NULL;
UNS32 * pwCobId = NULL;
@@ -125,12 +173,12 @@
(*d->post_sync)();
- /* only operational state allows PDO transmission */
+ /** only operational state allows PDO transmission */
if( d->nodeState != Operational )
return 0;
- /* So, the node is in operational state */
- /* study all PDO stored in the objects dictionary */
+ /** So, the node is in operational state */
+ /** study all PDO stored in the objects dictionary */
offsetObjdict = d->firstIndex->PDO_TRS;
lastIndex = d->lastIndex->PDO_TRS;
@@ -139,7 +187,7 @@
if(offsetObjdict) while( offsetObjdict <= lastIndex) {
switch( status ) {
- case state3: /* get the PDO transmission type */
+ case state3: /** get the PDO transmission type */
if (d->objdict[offsetObjdict].bSubCount <= 2) {
MSG_ERR(0x1004, "Subindex 2 not found at index ", 0x1800 + pdoNum);
return 0xFF;
@@ -148,8 +196,8 @@
MSG_WAR(0x3005, "Reading PDO at index : ", 0x1800 + pdoNum);
status = state4;
break;
- case state4: /* check if transmission type is after (this) SYNC */
- /* The message may not be transmited every SYNC but every n SYNC */
+ case state4: /** check if transmission type is after (this) SYNC */
+ /** The message may not be transmited every SYNC but every n SYNC */
if( (*pTransmissionType >= TRANS_SYNC_MIN) && (*pTransmissionType <= TRANS_SYNC_MAX) &&
(++d->count_sync[pdoNum] == *pTransmissionType) ) {
d->count_sync[pdoNum] = 0;
@@ -166,23 +214,23 @@
status = state11;
break;
}
- case state5: /* get PDO CobId */
+ case state5: /** get PDO CobId */
pwCobId = d->objdict[offsetObjdict].pSubindex[1].pObject;
MSG_WAR(0x3009, " PDO CobId is : ", *pwCobId);
status = state7;
break;
- case state7: /* get mapped objects number to transmit with this PDO */
+ case state7: /** get mapped objects number to transmit with this PDO */
pMappingCount = d->objdict[offsetObjdictMap].pSubindex[0].pObject;
MSG_WAR(0x300D, " Number of objects mapped : ",*pMappingCount );
status = state8;
- case state8: /* get mapping parameters */
+ case state8: /** get mapping parameters */
pMappingParameter = d->objdict[offsetObjdictMap].pSubindex[prp_j + 1].pObject;
MSG_WAR(0x300F, " got mapping parameter : ", *pMappingParameter);
MSG_WAR(0x3050, " at index : ", 0x1A00 + pdoNum);
MSG_WAR(0x3051, " sub-index : ", prp_j + 1);
status = state9;
- case state9: /* get data to transmit */
+ case state9: /** get data to transmit */
{
UNS8 ByteSize;
UNS8 tmp[]= {0,0,0,0,0,0,0,0};
@@ -191,7 +239,7 @@
Size = (UNS8)(*pMappingParameter); /* Size in bits */
ByteSize = 1 + ((Size - 1) >> 3); /*1->8 => 1 ; 9->16 => 2, ... */
objDict = getODentry(d, index, subIndex, tmp, &ByteSize, &dataType, 0 );
- /* copy bit per bit in little endian*/
+ /** copy bit per bit in little endian*/
CopyBits(Size, ((UNS8*)tmp), 0 , 0, (UNS8*)&d->process_var.data[offset>>3], offset%8, 0);
}
if( objDict != OD_SUCCESSFUL ){
@@ -205,7 +253,7 @@
status = state10;
break;
- case state10: /* loop to get all the data to transmit */
+ case state10: /** loop to get all the data to transmit */
if( prp_j < *pMappingCount ){
MSG_WAR(0x3014, " next variable mapped : ", prp_j);
status = state8;
--- a/src/timer.c Mon Jun 04 17:59:50 2007 +0200
+++ b/src/timer.c Tue Jun 05 16:41:38 2007 +0200
@@ -19,6 +19,15 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*!
+** @file timer.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date Tue Jun 5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
/* #define DEBUG_WAR_CONSOLE_ON */
/* #define DEBUG_ERR_CONSOLE_ON */
@@ -34,21 +43,31 @@
#define min_val(a,b) ((a<b)?a:b)
-/* --------- Use this to declare a new alarm --------- */
+/*!
+** ------- Use this to declare a new alarm ------
+**
+** @param d
+** @param id
+** @param callback
+** @param value
+** @param period
+**
+** @return
+**/
TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period)
{
/*printf("SetAlarm(UNS32 id=%d, TimerCallback_t callback=%x, TIMEVAL value=%d, TIMEVAL period=%d)\n", id, callback, value, period); */
TIMER_HANDLE i;
TIMER_HANDLE row_number = TIMER_NONE;
- /* in order to decide new timer setting we have to run over all timer rows */
+ /** in order to decide new timer setting we have to run over all timer rows */
for(i=0; i <= last_timer_raw + 1 && i < MAX_NB_TIMER; i++)
{
s_timer_entry *row = (timers+i);
- if (callback && /* if something to store */
- row->state == TIMER_FREE) /* and empty row */
- { /* just store */
+ if (callback && /** if something to store */
+ row->state == TIMER_FREE) /** and empty row */
+ { /** just store */
row->callback = callback;
row->d = d;
row->id = id;
@@ -60,33 +79,39 @@
}
}
- if (row_number != TIMER_NONE) /* if successfull **/
+ if (row_number != TIMER_NONE) /** if successfull **/
{
TIMEVAL real_timer_value;
TIMEVAL elapsed_time;
if (row_number == last_timer_raw + 1) last_timer_raw++;
- /* set next wakeup alarm if new entry is sooner than others, or if it is alone */
+ /** set next wakeup alarm if new entry is sooner than others, or if it is alone */
real_timer_value = min_val(value, TIMEVAL_MAX);
elapsed_time = getElapsedTime();
- /*printf("elapsed_time=%d real_timer_value=%d total_sleep_time=%d\n", elapsed_time, real_timer_value, total_sleep_time); */
+ /**printf("elapsed_time=%d real_timer_value=%d total_sleep_time=%d\n", elapsed_time, real_timer_value, total_sleep_time); */
if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value)
{
total_sleep_time = elapsed_time + real_timer_value;
setTimer(real_timer_value);
}
- /*printf("SetAlarm() return %d\n", row_number); */
+ /**printf("SetAlarm() return %d\n", row_number); */
return row_number;
}
return TIMER_NONE;
}
-/* --------- Use this to remove an alarm --------- */
+/*!
+** ----- Use this to remove an alarm ----
+**
+** @param handle
+**
+** @return
+**/
TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
{
- /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
+ /** Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
MSG_WAR(0x3320, "DelAlarm. handle = ", handle);
if(handle != TIMER_NONE)
{
@@ -99,14 +124,16 @@
return TIMER_NONE;
}
-
-/* --------- TimeDispatch is called on each timer expiration --------- */
+/*!
+** ------ TimeDispatch is called on each timer expiration ----
+**
+**/
void TimeDispatch()
{
TIMER_HANDLE i;
- TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
- /* First run : change timer state depending on time */
- /* Get time since timer signal */
+ TIMEVAL next_wakeup = TIMEVAL_MAX; /** used to compute when should normaly occur next wakeup */
+ /** First run : change timer state depending on time */
+ /** Get time since timer signal */
TIMEVAL overrun = getElapsedTime();
TIMEVAL real_total_sleep_time = total_sleep_time + overrun;
@@ -116,51 +143,51 @@
{
s_timer_entry *row = (timers+i);
- if (row->state & TIMER_ARMED) /* if row is active */
+ if (row->state & TIMER_ARMED) /** if row is active */
{
- if (row->val <= real_total_sleep_time) /* to be trigged */
+ if (row->val <= real_total_sleep_time) /** to be trigged */
{
/*printf("row->val(%d) <= (%d)real_total_sleep_time\n", row->val, real_total_sleep_time); */
- if (!row->interval) /* if simply outdated */
+ if (!row->interval) /** if simply outdated */
{
- row->state = TIMER_TRIG; /* ask for trig */
+ row->state = TIMER_TRIG; /** ask for trig */
}
- else /* or period have expired */
+ else /** or period have expired */
{
- /* set val as interval, with overrun correction */
+ /** set val as interval, with overrun correction */
row->val = row->interval - (overrun % row->interval);
row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
- /* Check if this new timer value is the soonest */
+ /** Check if this new timer value is the soonest */
next_wakeup = min_val(row->val,next_wakeup);
}
}
else
{
- /* Each armed timer value in decremented. */
+ /** Each armed timer value in decremented. */
row->val -= real_total_sleep_time;
- /* Check if this new timer value is the soonest */
+ /** Check if this new timer value is the soonest */
next_wakeup = min_val(row->val,next_wakeup);
}
}
}
- /* Remember how much time we should sleep. */
+ /** Remember how much time we should sleep. */
total_sleep_time = next_wakeup;
- /* Set timer to soonest occurence */
+ /** Set timer to soonest occurence */
setTimer(next_wakeup);
- /* Then trig them or not. */
+ /** Then trig them or not. */
for(i=0; i<=last_timer_raw; i++)
{
s_timer_entry *row = (timers+i);
if (row->state & TIMER_TRIG)
{
- row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */
+ row->state &= ~TIMER_TRIG; /** reset trig state (will be free if not periodic) */
if(row->callback)
- (*row->callback)(row->d, row->id); /* trig ! */
+ (*row->callback)(row->d, row->id); /** trig ! */
}
}
}