# HG changeset patch # User nico # Date 1181054498 -7200 # Node ID 05d95c45b388db7d38e17c066585d590431a7161 # Parent b6572d0336c3c32490ec1ed14f790246c8e16f53 Manual convertion -> latex -> pdf diff -r b6572d0336c3 -r 05d95c45b388 Makefile.in --- 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 diff -r b6572d0336c3 -r 05d95c45b388 doc/doxygen/Doxyfile --- 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 diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/100000000000006D000000A31EC8CB54.png Binary file doc/manual/en/Pictures/100000000000006D000000A31EC8CB54.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000000000000AA0000006014F74635.png Binary file doc/manual/en/Pictures/10000000000000AA0000006014F74635.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000000000000AB000000C88F594413.png Binary file doc/manual/en/Pictures/10000000000000AB000000C88F594413.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000000000000AC000000C9C3F53FA6.png Binary file doc/manual/en/Pictures/10000000000000AC000000C9C3F53FA6.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000000000000B6000000DF1EDD1E73.png Binary file doc/manual/en/Pictures/10000000000000B6000000DF1EDD1E73.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/100000000000022C000000DEDAD2140C.png Binary file doc/manual/en/Pictures/100000000000022C000000DEDAD2140C.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/1000000000000396000000FFC42573DA.png Binary file doc/manual/en/Pictures/1000000000000396000000FFC42573DA.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000000B7000000C66AF89CD5.png Binary file doc/manual/en/Pictures/10000201000000B7000000C66AF89CD5.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000001010000011DA724D25C.png Binary file doc/manual/en/Pictures/10000201000001010000011DA724D25C.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/100002010000013A0000004A96B0C1FF.png Binary file doc/manual/en/Pictures/100002010000013A0000004A96B0C1FF.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000001C4000000DD129D4661.png Binary file doc/manual/en/Pictures/10000201000001C4000000DD129D4661.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000001C40000010766961D7F.png Binary file doc/manual/en/Pictures/10000201000001C40000010766961D7F.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000001CB0000015F4FC09B68.png Binary file doc/manual/en/Pictures/10000201000001CB0000015F4FC09B68.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000001FC000001E5D65E8766.png Binary file doc/manual/en/Pictures/10000201000001FC000001E5D65E8766.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/1000020100000258000000832C6FFAB4.png Binary file doc/manual/en/Pictures/1000020100000258000000832C6FFAB4.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000002DE000001D82D89C224.png Binary file doc/manual/en/Pictures/10000201000002DE000001D82D89C224.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000002F30000020B23ED7F67.png Binary file doc/manual/en/Pictures/10000201000002F30000020B23ED7F67.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000003440000025ACC3FD2F1.png Binary file doc/manual/en/Pictures/10000201000003440000025ACC3FD2F1.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000003CA0000016604E6A5EF.png Binary file doc/manual/en/Pictures/10000201000003CA0000016604E6A5EF.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000003E7000001C7B0296577.png Binary file doc/manual/en/Pictures/10000201000003E7000001C7B0296577.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000003F9000002CF880931E7.png Binary file doc/manual/en/Pictures/10000201000003F9000002CF880931E7.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/Pictures/10000201000003F9000002CF8B0CDAEA.png Binary file doc/manual/en/Pictures/10000201000003F9000002CF8B0CDAEA.png has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/manual.pdf Binary file doc/manual/en/manual.pdf has changed diff -r b6572d0336c3 -r 05d95c45b388 doc/manual/en/manual.tex --- /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} diff -r b6572d0336c3 -r 05d95c45b388 src/dcf.c --- 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)(); } diff -r b6572d0336c3 -r 05d95c45b388 src/lifegrd.c --- 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 diff -r b6572d0336c3 -r 05d95c45b388 src/nmtMaster.c --- 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); } - - - - - - - - diff -r b6572d0336c3 -r 05d95c45b388 src/nmtSlave.c --- 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); } diff -r b6572d0336c3 -r 05d95c45b388 src/objacces.c --- 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){} diff -r b6572d0336c3 -r 05d95c45b388 src/pdo.c --- 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 + + + diff -r b6572d0336c3 -r 05d95c45b388 src/sdo.c --- 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); diff -r b6572d0336c3 -r 05d95c45b388 src/states.c --- 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; } diff -r b6572d0336c3 -r 05d95c45b388 src/sync.c --- 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; diff -r b6572d0336c3 -r 05d95c45b388 src/timer.c --- 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) ((astate == 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 ! */ } } }