Refs #268. Merged /hostlib branch back into the trunk.
git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@270 5dc33758-31d5-4daf-9ae8-b24bf3d40d73
This commit is contained in:
parent
4a09db8197
commit
f469148355
|
@ -0,0 +1,6 @@
|
|||
[InternetShortcut]
|
||||
URL=https://www.feaser.com/openblt/doku.php?id=manual:bootcommander
|
||||
IDList=
|
||||
HotKey=0
|
||||
IconFile=
|
||||
IconIndex=0
|
|
@ -0,0 +1,6 @@
|
|||
[InternetShortcut]
|
||||
URL=https://www.feaser.com/openblt/doku.php?id=manual:libopenblt
|
||||
IDList=
|
||||
HotKey=0
|
||||
IconFile=
|
||||
IconIndex=0
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
|||
:: Batch file to generate a reference manual from the comments in the source code, with
|
||||
:: Doxygen. The following tools should be installed and added to the path:
|
||||
:: - DoxyGen (doxygen.exe)
|
||||
:: - Graphviz (dot.exe)
|
||||
:: - MikTex (pdflatex.exe)
|
||||
:: - HTML Help Workshop compiler (hhc.exe)
|
||||
if exist ..\RM_BootCommander.pdf del ..\RM_BootCommander.pdf
|
||||
if exist ..\RM_BootCommander.chm del ..\RM_BootCommander.chm
|
||||
doxygen.exe DoxyfileBootCommander
|
||||
call .\output\BootCommander\latex\make.bat
|
||||
call copy .\output\BootCommander\latex\refman.pdf ..\RM_BootCommander.pdf
|
||||
:: Remove the comment on the next line to automatically open the generated PDF file
|
||||
:: call start "C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe" ..\RM_BootCommander.pdf
|
||||
:: Remove the comment on the next line to automatically open the generated CHM file
|
||||
:: start .\..\RM_BootCommander.chm
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
|||
:: Batch file to generate a reference manual from the comments in the source code, with
|
||||
:: Doxygen. The following tools should be installed and added to the path:
|
||||
:: - DoxyGen (doxygen.exe)
|
||||
:: - Graphviz (dot.exe)
|
||||
:: - MikTex (pdflatex.exe)
|
||||
:: - HTML Help Workshop compiler (hhc.exe)
|
||||
if exist ..\RM_LibOpenBLT.pdf del ..\RM_LibOpenBLT.pdf
|
||||
if exist ..\RM_LibOpenBLT.chm del ..\RM_LibOpenBLT.chm
|
||||
doxygen.exe DoxyfileLibOpenBLT
|
||||
call .\output\LibOpenBLT\latex\make.bat
|
||||
call copy .\output\LibOpenBLT\latex\refman.pdf ..\RM_LibOpenBLT.pdf
|
||||
:: Remove the comment on the next line to automatically open the generated PDF file
|
||||
:: call start "C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe" ..\RM_LibOpenBLT.pdf
|
||||
:: Remove the comment on the next line to automatically open the generated CHM file
|
||||
:: start .\..\RM_LibOpenBLT.chm
|
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
After Width: | Height: | Size: 80 KiB |
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 93 KiB |
|
@ -0,0 +1,148 @@
|
|||
#****************************************************************************************
|
||||
# \file CMakeLists.txt
|
||||
# \brief CMake descriptor file for BootCommander command line program.
|
||||
# \internal
|
||||
#----------------------------------------------------------------------------------------
|
||||
# C O P Y R I G H T
|
||||
#----------------------------------------------------------------------------------------
|
||||
# Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
#
|
||||
#----------------------------------------------------------------------------------------
|
||||
# L I C E N S E
|
||||
#----------------------------------------------------------------------------------------
|
||||
# This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
# PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
# should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
#
|
||||
# \endinternal
|
||||
#****************************************************************************************
|
||||
# Specify the version being used aswell as the language
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
|
||||
#****************************************************************************************
|
||||
# Project configuration
|
||||
#****************************************************************************************
|
||||
# Specify the project name
|
||||
project(BootCommander)
|
||||
|
||||
# Build debug version by default
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
|
||||
|
||||
#****************************************************************************************
|
||||
# Options
|
||||
#****************************************************************************************
|
||||
# Add option with default value to disable the generation of the PC-lint target. It can
|
||||
# be overridden on the command line when CMake is called using the following parameter:
|
||||
# -DLINT_ENABLED=ON
|
||||
option(LINT_ENABLED "Configurable to enable/disable the PC-lint target" OFF)
|
||||
|
||||
|
||||
#****************************************************************************************
|
||||
# Directories
|
||||
#****************************************************************************************
|
||||
# Set the output directory
|
||||
set (PROJECT_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../../..)
|
||||
|
||||
# Set the output directory for the generic no-config case (e.g. with mingw)
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
# Set the output directory for multi-config builds (e.g. msvc)
|
||||
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
|
||||
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
|
||||
|
||||
# Set OpenBLT library related directory locations
|
||||
set(LIBOPENBLT_INC ${PROJECT_SOURCE_DIR}/../LibOpenBLT)
|
||||
set(LIBOPENBLT_LIB ${PROJECT_OUTPUT_DIRECTORY})
|
||||
|
||||
#****************************************************************************************
|
||||
# Compiler flags
|
||||
#****************************************************************************************
|
||||
# Set platform specific compiler macro PLATFORM_XXX
|
||||
if(WIN32)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_WIN32 -D_CRT_SECURE_NO_WARNINGS")
|
||||
elseif(UNIX)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_LINUX")
|
||||
endif(WIN32)
|
||||
|
||||
|
||||
#***************************************************************************************
|
||||
# Includes
|
||||
#****************************************************************************************
|
||||
# Set include directories
|
||||
include_directories("${PROJECT_SOURCE_DIR}" "${LIBOPENBLT_INC}")
|
||||
|
||||
# Add search path for the linker
|
||||
link_directories("${LIBOPENBLT_LIB}")
|
||||
|
||||
|
||||
#***************************************************************************************
|
||||
# Files
|
||||
#****************************************************************************************
|
||||
# Get header files from the root directory
|
||||
file(GLOB INCS_ROOT "*.h")
|
||||
set(INCS ${INCS_ROOT})
|
||||
|
||||
# Add sources
|
||||
set(
|
||||
PROG_SRCS
|
||||
main.c
|
||||
${LIBOPENBLT_INC}/openblt.h
|
||||
${INCS}
|
||||
)
|
||||
|
||||
# Set library name. When GNU GCC is used, the name to the static library file is used,
|
||||
# otherwise the shared library is used by default. This works fine too, but the static
|
||||
# library makes it a bit easier to move the target executable around on the file system.
|
||||
if(CMAKE_C_COMPILER_ID MATCHES GNU)
|
||||
set (LIBOPENBLT_LIBNAME libopenblt.a)
|
||||
else()
|
||||
set (LIBOPENBLT_LIBNAME openblt)
|
||||
endif()
|
||||
|
||||
|
||||
#***************************************************************************************
|
||||
# Targets
|
||||
#****************************************************************************************
|
||||
# Set main target. Use "make BootCommander" to individually build the program.
|
||||
add_executable(
|
||||
BootCommander
|
||||
${PROG_SRCS}
|
||||
)
|
||||
|
||||
# Add libraries
|
||||
target_link_libraries(BootCommander ${LIBOPENBLT_LIBNAME})
|
||||
|
||||
# Only generate the PC-lint taget if the option is enabled. Use "make BootCommander_LINT"
|
||||
# to lint the project sources
|
||||
if(LINT_ENABLED)
|
||||
# Include PC-lint configuration file for the correct compiler. Currently GNU GCC and
|
||||
# Microsoft Visual Studio are supported.
|
||||
if(CMAKE_C_COMPILER_ID MATCHES GNU)
|
||||
include(${PROJECT_SOURCE_DIR}/lint/gnu/pc_lint.cmake)
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
include(${PROJECT_SOURCE_DIR}/lint/msvc/pc_lint.cmake)
|
||||
endif()
|
||||
|
||||
# Generate the PC-lint target.
|
||||
if(COMMAND add_pc_lint)
|
||||
add_pc_lint(BootCommander ${PROG_SRCS})
|
||||
endif(COMMAND add_pc_lint)
|
||||
endif(LINT_ENABLED)
|
||||
|
||||
|
||||
#*********************************** end of CMakeLists.txt ******************************
|
|
@ -0,0 +1,129 @@
|
|||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifndef CO_GCC_H_
|
||||
#define CO_GCC_H_
|
||||
/*lint -save -w1 */
|
||||
|
||||
#ifdef _lint /* Make sure no compiler comes this way */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Standard library headers typically define the assert macro so that it
|
||||
expands to a complicated conditional expression that uses special
|
||||
funtions that Lint does not know about by default. For linting
|
||||
purposes, we can simplify things a bit by forcing assert() to expand to
|
||||
a call to a special function that has the appropriate 'assert'
|
||||
semantics.
|
||||
*/
|
||||
//lint -function( __assert, __lint_assert )
|
||||
void __lint_assert( int );
|
||||
//lint ++d"assert(e)=__lint_assert(!!(e))"
|
||||
//(++d makes this definition permanently immutable for the Lint run.)
|
||||
//Now that we've made our own 'assert', we need to keep people from being
|
||||
//punished when the marco in 'assert.h' appears not to be used:
|
||||
//lint -efile(766,*assert.h)
|
||||
|
||||
typedef char *__builtin_va_list;
|
||||
|
||||
/*lint -e{171} */
|
||||
__builtin_va_list __lint_init_va(...);
|
||||
|
||||
void __builtin_va_end( __builtin_va_list );
|
||||
/*lint
|
||||
++d"__builtin_va_start(ap,parmN)=((ap)=__lint_init_va(parmN))"
|
||||
++d"__builtin_va_arg(a,b)=(*( ((b) *) ( (((a) += sizeof(b)) - sizeof(b) )))"
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
The headers included below must be generated; For C++, generate
|
||||
with:
|
||||
|
||||
g++ [usual build options] -E -dM t.cpp >lint_cppmac.h
|
||||
|
||||
For C, generate with:
|
||||
|
||||
gcc [usual build options] -E -dM t.c >lint_cmac.h
|
||||
|
||||
...where "t.cpp" and "t.c" are empty source files.
|
||||
|
||||
It's important to use the same compiler options used when compiling
|
||||
project code because they can affect the existence and precise
|
||||
definitions of certain predefined macros. See gcc-readme.txt for
|
||||
details and a tutorial.
|
||||
*/
|
||||
#if defined(__cplusplus)
|
||||
# include "lint_cppmac.h" // DO NOT COMMENT THIS OUT. DO NOT SUPPRESS ERROR 322. (If you see an error here, your Lint configuration is broken; check -i options and ensure that you have generated lint_cppmac.h as documented in gcc-readme.txt. Otherwise Gimpel Software cannot support your configuration.)
|
||||
#else
|
||||
# include "lint_cmac.h" // DO NOT COMMENT THIS OUT. DO NOT SUPPRESS ERROR 322. (If you see an error here, your Lint configuration is broken; check -i options and ensure that you have generated lint_cmac.h as documented in gcc-readme.txt. Otherwise Gimpel Software cannot support your configuration.)
|
||||
#endif
|
||||
|
||||
/* If the macro set given by the generated macro files must be adjusted in
|
||||
order for Lint to cope, then you can make those adjustments here.
|
||||
*/
|
||||
|
||||
#define LINT_CO_GCC_H_GCC_VERSION ( __GNUC__ * 10000 + \
|
||||
__GNUC_MINOR__ * 100 + \
|
||||
__GNUC_PATCHLEVEL__ )
|
||||
|
||||
/* The following is a workaround for versions of GCC with bug 25717, in
|
||||
which the preprocessor does not dump a #define directive for __STDC__
|
||||
when -dM is given:
|
||||
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25717
|
||||
|
||||
We know the unconditional definition of __STDC__ was introduced no
|
||||
later than version 3.0; the preprocessor bug was fixed no later than
|
||||
version 4.1.0.
|
||||
*/
|
||||
#if ( LINT_CO_GCC_H_GCC_VERSION >= 30000 && \
|
||||
LINT_CO_GCC_H_GCC_VERSION < 40100 )
|
||||
# define __STDC__ 1
|
||||
#endif
|
||||
|
||||
#if !__cplusplus && !__STRICT_ANSI__ && __STDC_VERSION__ < 199901L
|
||||
/* apparently, the code is compiled with -std=gnu89 (as opposed to -std=c89),
|
||||
so: */
|
||||
/*lint -rw_asgn(inline,__inline) */
|
||||
#endif
|
||||
|
||||
#if LINT_CO_GCC_H_GCC_VERSION >= 40300
|
||||
# define __COUNTER__ __lint__COUNTER__
|
||||
//lint +rw( *type_traits ) // Enable type traits support
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#if _lint >= 909 // For 9.00i and later:
|
||||
//// __attribute__ is GCC's __attribute__:
|
||||
//
|
||||
//lint -rw_asgn(__attribute__,__gcc_attribute__)
|
||||
//lint -rw_asgn(__attribute, __gcc_attribute__)
|
||||
//
|
||||
//// Prevent "__attribute__" from being defined as a macro:
|
||||
//
|
||||
//lint --u"__attribute__"
|
||||
//lint --u"__attribute"
|
||||
//
|
||||
//// Because an attribute-specifier is a form of
|
||||
//// declaration-modifier, and because it can appear at the
|
||||
//// beginning of a decl-specifier-seq, we must enable "Early
|
||||
//// Modifiers":
|
||||
//
|
||||
//lint +fem
|
||||
#else // for 9.00h and earlier:
|
||||
//lint -d__attribute__()=
|
||||
//lint -d__attribute()=
|
||||
#endif
|
||||
|
||||
#endif /* _lint */
|
||||
/*lint -restore */
|
||||
#endif /* CO_GCC_H_ */
|
|
@ -0,0 +1,209 @@
|
|||
/* Date Stamp */ -d"_lint_co_gcc_lnt=co-gcc.lnt modified 12-Jun-2014"
|
||||
/* To document usage use: -message( "Using " _lint_co_gcc_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
/* co-gcc.lnt: This is the seed file for configuring Lint for use with
|
||||
GCC versions 2.95.3 and later.
|
||||
|
||||
Like all compiler options files this file is intended to be used
|
||||
as follows:
|
||||
|
||||
lint co-gcc.lnt source-files-to-be-linted
|
||||
|
||||
Some of the information that co-gcc.lnt requires needs to be furnished
|
||||
with the help of the gcc system itself. The easiest way to generate
|
||||
this information is to use the makefile co-gcc.mak (supplied with the
|
||||
Lint distribution) in an invocation of GNU Make; for details, see the
|
||||
commentary at the top of co-gcc.mak.
|
||||
*/
|
||||
|
||||
-cgnu // Notifies FlexeLint that gcc is being used.
|
||||
|
||||
// ===========================
|
||||
// Preprocessor Configuration:
|
||||
+fdi // GCC starts its #include search in the directory of the including
|
||||
// file.
|
||||
|
||||
++fln // Allow:
|
||||
// # digit-sequence " [s-char-sequence] " new-line
|
||||
// as a synonym for:
|
||||
// # line digit-sequence " [s-char-sequence] " new-line
|
||||
// GCC additionally allows flag values to follow the
|
||||
// s-char-sequence, but currently Lint ignores them.
|
||||
|
||||
-header(co-gcc.h) // Includes headers generated by GCC (bringing in
|
||||
// predefined macros).
|
||||
+libh(co-gcc.h) // Marks that header as library code.
|
||||
|
||||
gcc-include-path.lnt // This .lnt file should contain --i options
|
||||
// and should be generated by invoking gcc with its '-v' option.
|
||||
// (GCC's implicit #include search path is presented in the output.)
|
||||
// This happens automatically when 'make -f co-gcc.mak' is invoked.
|
||||
|
||||
// Assertion directives (a feature of GCC's preprocessor) have been
|
||||
// considered obsolete in GCC's documentation since version 3.0, so we do
|
||||
// not use them here. If support for #assert is needed in the form of a
|
||||
// lint option, one may use '-a#' like so:
|
||||
// -a#machine(i386) // #assert's machine(i386) (SVR4 facility).
|
||||
|
||||
// File extensions:
|
||||
// From the GCC man page:
|
||||
//
|
||||
// file.cc
|
||||
// file.cp
|
||||
// file.cxx
|
||||
// file.cpp
|
||||
// file.CPP
|
||||
// file.c++
|
||||
// file.C
|
||||
// C++ source code that must be preprocessed. Note that in .cxx, the
|
||||
// last two letters must both be literally x. Likewise, .C refers to
|
||||
// a literal capital C.
|
||||
//
|
||||
// We emulate this with:
|
||||
|
||||
+cpp(.cc)
|
||||
+cpp(.cp)
|
||||
+cpp(.cxx)
|
||||
+cpp(.cpp)
|
||||
+cpp(.c++)
|
||||
// Note the exceptions:
|
||||
// +cpp(.CPP)
|
||||
// +cpp(.C)
|
||||
// These are commented out for the default config because they seem to
|
||||
// cause trouble more often than not. For starters, it is problematic
|
||||
// with filesystems that are case-insensitive (which has become common
|
||||
// even on some POSIX systems).
|
||||
|
||||
// =============
|
||||
// Size Options:
|
||||
// +fwc // wchar_t might be builtin; if so, uncomment this option. (NOTE:
|
||||
// // this option needs to be set before a size option is given for
|
||||
// // wchar_t; see the documentation for -sw# in the Lint manual.)
|
||||
|
||||
size-options.lnt // This .lnt file should be generated (preferrably
|
||||
// by a program created by invoking GCC with the compile options that
|
||||
// are used in the compilation of the project to be linted). This
|
||||
// happens automatically when 'make -f co-gcc.mak' is invoked.
|
||||
|
||||
|
||||
// ===========================================
|
||||
// +rw and -d options to cope with GNU syntax:
|
||||
+ppw(ident) // Tolerate #ident
|
||||
+ppw(warning)
|
||||
|
||||
// GCC provides alternative spellings of certain keywords:
|
||||
+rw(__inline)
|
||||
-rw_asgn(__inline__,__inline)
|
||||
-rw_asgn(__header_always_inline,__inline)
|
||||
-rw_asgn(__header_inline,__inline)
|
||||
|
||||
-rw_asgn(__signed__,signed)
|
||||
-rw_asgn(__signed,signed)
|
||||
-rw_asgn( __volatile__, volatile )
|
||||
-rw_asgn( __volatile, volatile )
|
||||
+rw(restrict)
|
||||
-rw_asgn(__restrict,restrict)
|
||||
-rw_asgn(__restrict__,restrict)
|
||||
++d"__const=const" // gconv.h uses __const rather than const
|
||||
++d"const=const" // ensure const expands to const.
|
||||
|
||||
-rw_asgn( asm, _up_to_brackets )
|
||||
-rw_asgn( __asm, _up_to_brackets )
|
||||
-rw_asgn( __asm__, _up_to_brackets )
|
||||
// This re-definition of the various spellings of the asm keyword enables
|
||||
// Lint to pass gracefully over expression-statements like:
|
||||
// __asm __volatile ("fsqrt" : "=t" (__result) : "0" (__x));
|
||||
// But it may be necessary to suppress certain error messages that are
|
||||
// triggered by tokens that are part of an assembly declaration or
|
||||
// statement. For example:
|
||||
|
||||
-d"__asm__(p...)=/*lint -e{19}*/ __asm__(p)"
|
||||
|
||||
// ...causes Lint to be quiet about the semicolon that follows an
|
||||
// __asm__() declaration. Note, the -e{N} form of suppression takes
|
||||
// effect only for the forward-declaration, definition or
|
||||
// [possibly-compound] statement that immediately follows. Because a
|
||||
// semicolon is seen as a declaration-terminator, Error 19 will be
|
||||
// re-enabled immediately after the semicolon in '__asm__(...);'.
|
||||
// (The elipsis after the macro parameter p allows zero or more commas to
|
||||
// appear in the operand.)
|
||||
//
|
||||
// If you encounter other diagnostics that appear to need suppression in
|
||||
// or near assembly regions, please let us know!
|
||||
//
|
||||
-esym(123,__asm__)
|
||||
|
||||
-rw_asgn(__alignof__,__alignof)
|
||||
|
||||
// "__extension__" is GCC's way of allowing the use of non-standard
|
||||
// constructs in a strict Standard-conforming mode. We don't currently
|
||||
// have explicit support for it, but we can use local suppressions. For
|
||||
// example, we can use -e(160) so that we will not see any Errors about
|
||||
// GNU statement-expressions wrapped in __extension__().
|
||||
++d"__extension__=/*lint -e(160) */"
|
||||
|
||||
++d"__null=0"
|
||||
+rw(_to_semi) // needed for the two macros above.
|
||||
+rw(__typeof__) // activate __typeof__ keyword
|
||||
-d"__typeof=__typeof__" // an alternative to using __typeof__
|
||||
|
||||
-rw(__except) // This MS reserved word is used as an identifier
|
||||
+rw( __complex__, __real__, __imag__ ) // reserved words that can be ignored.
|
||||
++d"__builtin_strchr=(char*)" // permits the inline definition ...
|
||||
++d"__builtin_strpbrk=(char*)" // of these functions to be linted ...
|
||||
++d"__builtin_strrchr=(char*)" // without drawing a complaint
|
||||
++d"__builtin_strstr=(char*)" // about the use of a non-standard name
|
||||
++d"__PRETTY_FUNCTION__=___function___" // lint defines ___function___ internally
|
||||
++d"__FUNCTION__=___function___" // lint defines ___function___ internally
|
||||
++d"__func__=___function___" // Some C++ modes suport the implicit __func__
|
||||
// identifier.
|
||||
-ident($)
|
||||
|
||||
// =========================================================
|
||||
// Other options supporting GNU C/C++ syntax:
|
||||
+fld // enables the processing of _L_abel _D_esignators E.g.:
|
||||
// union { double d; int i; } u = { d: 3.141 };
|
||||
|
||||
// =========================================================
|
||||
// Generally useful suppressions:
|
||||
-wlib(1) // sets the warning level within library headers to 1
|
||||
// (no warnings, just syntax errors). Comment out if you
|
||||
// are actually linting library headers.
|
||||
-elib(123) // 123 is really a warning, but it's in the "Error" range.
|
||||
-elib(93) // allow newlines within quoted string arguments to macros
|
||||
-elib(46) // allow bit fields to have integral types other than
|
||||
// '_Bool' and 'int'.
|
||||
-elibsym(628) // Suppress 628 for __builtin symbols.
|
||||
|
||||
-esym(528,__huge_val,__nan,__qnan,__qnanf,__snan,__snanf)
|
||||
// We don't care if we don't reference some GNU functions
|
||||
-esym(528,__gnu_malloc,__gnu_calloc)
|
||||
|
||||
// The following functions exhibit variable return modes.
|
||||
// That is, they may equally-usefully be called for a value
|
||||
// as called just for their effects. Accordingly we inhibit
|
||||
// Warning 534 for these functions.
|
||||
// Feel free to add to or subtract from this list.
|
||||
|
||||
-esym(534,close,creat,fclose,fprintf,fputc)
|
||||
-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)
|
||||
-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)
|
||||
-esym(534,strncat,strncpy,unlink,write)
|
||||
|
||||
// For non-ANSI compilers we suppress messages 515 and 516
|
||||
// for functions known to have variable argument lists.
|
||||
// For ANSI compilers, header files should take care of this.
|
||||
|
||||
-esym(515,fprintf,printf,sprintf,fscanf,scanf,sscanf)
|
||||
-esym(516,fprintf,printf,sprintf,fscanf,scanf,sscanf)
|
||||
-esym(1702,*operator<<,*operator>>)
|
||||
-esym(534,*operator<<,*operator>>)
|
||||
-esym(1055,*__builtin*)
|
||||
-esym(718,*__builtin*) // The compiler does not need these ...
|
||||
-esym(746,*__builtin*) // declared and it knows their prototypes.
|
|
@ -0,0 +1,5 @@
|
|||
--i/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/include
|
||||
--i/usr/local/include
|
||||
--i/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/include-fixed
|
||||
--i/usr/include
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
|
||||
Using FlexeLint with GCC
|
||||
|
||||
These notes describe how to use the option file co-gcc.lnt which serves
|
||||
as a replacement for the older co-gnu.lnt and co-gnu3.lnt options files.
|
||||
|
||||
--- Quick Start ---
|
||||
|
||||
If you just want a quick-and-dirty Lint configuration (one that enables
|
||||
you to use Standard Library headers and system headers) then use the
|
||||
makefile 'co-gcc.mak' (supplied with the Lint distribution) in an
|
||||
invocation of GNU Make like so:
|
||||
|
||||
make -f co-gcc.mak
|
||||
|
||||
... which should generate the following files (provided that 'gcc', 'g++'
|
||||
and 'awk' are each found in your $PATH):
|
||||
|
||||
lint_cmac.h
|
||||
lint_cppmac.h
|
||||
gcc-include-path.lnt
|
||||
size-options.lnt
|
||||
|
||||
(co-gcc.lnt depends on these files, so they must be generated before you
|
||||
do anything else.)
|
||||
|
||||
That's it! You should now be able to run:
|
||||
|
||||
flint co-gcc.lnt [source files]
|
||||
|
||||
Note that Lint must be able to find co-gcc.lnt and the files referenced
|
||||
therein. If you want to keep them in a separate directory (e.g.,
|
||||
/usr/local/etc/flint) from the one where you will invoke Lint (e.g.,
|
||||
~/some-project/src), you'll need to specify the former with a '-i' option
|
||||
so that Lint will know where to look. In that case, the invocation would
|
||||
look like:
|
||||
|
||||
flint -i /usr/local/etc/flint co-gcc.lnt [source files]
|
||||
|
||||
If your project is compiled without any explicit command-line switches
|
||||
other than '-c' then this invocation alone might be all that you need to
|
||||
get started linting your project. Otherwise it probably won't suffice.
|
||||
For a Lint configuration that better matches the way you compile your
|
||||
code, you should at least read the 'usage' note at the top of co-gcc.mak.
|
||||
|
||||
For a motivation for the contents of co-gcc.mak, and to better understand
|
||||
the configuration issues in general, please read on.
|
||||
|
||||
--- Introduction ---
|
||||
|
||||
The configuration of Lint for use with GCC-compiled sources is complicated
|
||||
by two major issues:
|
||||
|
||||
First, GCC defines a large number of preprocessor macros internally (i.e.,
|
||||
it defines a lot of macros for which there are no '#define' directives in
|
||||
any source file that Lint can read.). Unless this issue is resolved for
|
||||
each project, Lint will not see the same sequence of C/C++ tokens as GCC
|
||||
when it tries to analyze your program, and as a result it will not see the
|
||||
same set of declarations; consequently you'll see lots of spurious
|
||||
messages because the analysis will reflect that of a program that is
|
||||
truly ill-formed (unlike the program seen by GCC).
|
||||
|
||||
Second, GCC is aware of several built-in functions. Most of them can be
|
||||
presented to Lint as ordinary forward-declarations of functions so as to
|
||||
avoid undesired diagnostics claiming that these functions were not
|
||||
declared before the first point of use. Note, these declarations do not
|
||||
necessarily need to be presented to GCC.
|
||||
|
||||
--- Solving the Preprocessor Problem ---
|
||||
|
||||
Before we get started, we'll need an empty C source file. Call it
|
||||
'empty.c' and save it to disk. Next, use your favorite command
|
||||
interpreter environment (such as sh in Unix-like environments or cmd.exe
|
||||
on Windows) and go to the directory containing 'empty.c'. Verify that you
|
||||
can run GCC by doing the following:
|
||||
|
||||
gcc -v
|
||||
|
||||
If your environment is properly set up you should see a version string.
|
||||
(You'll also want to verify that this is the same GCC executable used to
|
||||
compile your sources; check the PATH environment variable or try running
|
||||
'which gcc'.)
|
||||
|
||||
Assuming that worked, you can now try the following (and note that case,
|
||||
as with C/C++ identifiers, is important.):
|
||||
|
||||
gcc -E -dM empty.c
|
||||
|
||||
On one system, we then see definitions like:
|
||||
|
||||
#define __DBL_MIN_EXP__ (-1021)
|
||||
#define __FLT_MIN__ 1.17549435e-38F
|
||||
#define __DEC64_DEN__ 0.000000000000001E-383DD
|
||||
|
||||
... followed by about a hundred more '#define' directives. What just
|
||||
happened? We passed two options to gcc; the first one, '-E', means,
|
||||
"don't run the compiler; just run the preprocessor". The option '-dM'
|
||||
(not to be confused with '-DM', which is completely different) means,
|
||||
"don't generate preprocessor output; instead, only dump all macro
|
||||
definitions, including those defined internally".
|
||||
|
||||
With this output, we are now halfway to the point of having a preprocessor
|
||||
configuration for Lint. First, let's redirect those macros to a file:
|
||||
|
||||
gcc -E -dM empty.c >lint_cmac.h
|
||||
|
||||
Next, let's test our configuration: make a simple C source file
|
||||
containing the "Hello, world" program in a file called 't.c' (in the same
|
||||
directory as 'empty.c')
|
||||
|
||||
#include <stdio.h>
|
||||
int main () {
|
||||
printf( "hello, world!\n" );
|
||||
}
|
||||
|
||||
To lint this program, first copy the lnt file (co-gcc.lnt) and the
|
||||
associated header (co-gcc.h) into the same directory. Next, create two
|
||||
new empty files:
|
||||
|
||||
size-options.lnt
|
||||
gcc-include-path.lnt
|
||||
|
||||
... and save them to disk. Then make a file called 'std.lnt' which will
|
||||
(at first) contain only:
|
||||
|
||||
co-gcc.lnt
|
||||
|
||||
This tells Lint, "process the arguments in co-gcc.lnt". Two of those
|
||||
arguments are:
|
||||
|
||||
-header(co-gcc.h) // #include's headers generated by GCC.
|
||||
+libh(co-gcc.h) // Marks co-gcc.h as library code.
|
||||
|
||||
'-header(co-gcc.h)' means "behave as if each primary source file began
|
||||
with '#include "co-gcc.h"'. (Note that co-gcc.h includes "lint_cmac.h"
|
||||
when Lint runs in C language mode.)
|
||||
|
||||
Finally, try running:
|
||||
|
||||
/path/to/flint std.lnt t.c
|
||||
|
||||
... or, on Windows:
|
||||
|
||||
[drive-letter]:\path\to\lint-nt std.lnt t.c
|
||||
|
||||
Next we'll see output similar to the following:
|
||||
|
||||
FlexeLint for C/C++ (Unix/386) Vers. 9.00c, Copyright Gimpel Software
|
||||
1985-2009
|
||||
|
||||
--- Module: t.c (C)
|
||||
_
|
||||
#include <stdio.h>
|
||||
t.c 3 Error 322: Unable to open include file 'stdio.h'
|
||||
|
||||
What went wrong? The problem is that we haven't yet addressed the other
|
||||
half of the preprocessor configuration, namely: the ordered sequence of
|
||||
directories to search for system headers. Fortunately GCC already knows
|
||||
this list and gives us a way to discover it. Just run:
|
||||
|
||||
gcc -c -v empty.c
|
||||
|
||||
On one system (specifically, Mac OS X on Intel), that yields a lot of
|
||||
verbose output including these lines:
|
||||
|
||||
#include "..." search starts here:
|
||||
#include <...> search starts here:
|
||||
/usr/local/include
|
||||
/usr/lib/gcc/i686-apple-darwin8/4.0.1/include
|
||||
/usr/include
|
||||
/System/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
End of search list.
|
||||
|
||||
(Naturally, that list will look a bit different in different
|
||||
environments.) To make Lint search for system headers in the same way, we
|
||||
need to take that output from GCC and use it to make a set of options of
|
||||
the form --i[directory]. E.g. on the same system, that means that in
|
||||
gcc-include-path.lnt, I should place the following --i options:
|
||||
|
||||
--i/usr/local/include
|
||||
--i/usr/lib/gcc/i686-apple-darwin8/4.0.1/include
|
||||
--i/usr/include
|
||||
--i/System/Library/Frameworks
|
||||
--i/Library/Frameworks
|
||||
|
||||
(Note, arguments to Lint are processed in order, so the --i options must
|
||||
appear before t.c or they will not take effect in time.)
|
||||
|
||||
In this case, none of the directory names contains a space, but if one of
|
||||
them did we would have to surround its name with quotes as in:
|
||||
|
||||
--i"/usr/local/include"
|
||||
|
||||
Now let's try linting "hello, world" again:
|
||||
|
||||
/path/to/flint std.lnt t.c
|
||||
|
||||
This time we should see no error messages. Are we done yet? Not quite.
|
||||
First, let's test our configuration against all of the C Standard Library
|
||||
headers. Modify t.c to:
|
||||
|
||||
#include <assert.h>
|
||||
#include <iso646.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <wctype.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int main () {
|
||||
printf( "hello, world!\n" );
|
||||
}
|
||||
|
||||
|
||||
... and try linting again:
|
||||
|
||||
/path/to/flint std.lnt t.c
|
||||
|
||||
This time you should see a number of messages; in particular, you should
|
||||
see Info 766 issued for most of these headers since they were not used.
|
||||
you may also see some legitimate warnings, and you may see an Error or two
|
||||
about 'wchar_t'. (Note, if it seems as though your port of GCC recognizes
|
||||
wchar_t as a keyword instead of an identifier then uncomment the use of
|
||||
'+fwc' in your copy of co-gcc.lnt).
|
||||
|
||||
[NOTE: we should point out that the option -wlib(1) is in co-gcc.lnt for a
|
||||
reason. Please note that we *strongly* recommend against the use of
|
||||
options like -wlib(0) or -elib(*). If you see syntax error messages about
|
||||
library header code, odds are that something is wrong with the Lint
|
||||
configuration; so you'll do yourself no favors by silencing Lint when it
|
||||
sees constructs that Lint's parser doesn't know how to handle. If you need
|
||||
help with correcting your configuration, please check the Lint manual or
|
||||
contact us.]
|
||||
|
||||
We should really be done now, right? Well, not quite. A remaining issue
|
||||
is that the set of predefined macros (dumped into "lint_cmac.h" earlier)
|
||||
depends not only on things like the target system and the version of GCC;
|
||||
it also depends on the options that you pass to GCC when you compile your
|
||||
program. E.g., if we invoke:
|
||||
|
||||
gcc -O3 -E -dM empty.c >lint_cmac.h
|
||||
|
||||
... then (with the version of GCC we tested) lint_cmac.h will no longer
|
||||
contain a definition for the macro '__NO_INLINE__' and contains a new
|
||||
definition for '__OPTIMIZE__'. So when you generate macros, you should be
|
||||
careful to pass in the full set of options used when you compile.
|
||||
Ideally, you should establish a target in your build system that
|
||||
re-generates the predefined macro header whenever your build configuration
|
||||
changes; that way you'll seldom need to think about it again and Lint's
|
||||
preprocessor configuration will always match the compiler's.
|
||||
|
||||
Assuming you've generated the right set of predefined macros for your
|
||||
build settings, you should now try Linting a single primary source file in
|
||||
your project. Since we're just starting out, let's run with -w1 (i.e.,
|
||||
with the warning level set to one) so that we can deal with any syntax
|
||||
errors that pop up:
|
||||
|
||||
flint std.lnt -u -w1 some-project-file.c
|
||||
|
||||
Again, remember that syntax errors at this stage are likely due to a
|
||||
misconfiguration; please check the Lint manual for likely remedies or
|
||||
contact us if the solution is not obvious.
|
||||
|
||||
Once you've taken care of all syntax errors, try doing the same with all
|
||||
project files. We recommend placing the name of each project file in a
|
||||
.lnt file (often called project.lnt); e.g.:
|
||||
|
||||
file1.c
|
||||
file2.c
|
||||
[...etc.]
|
||||
|
||||
... and invoke Lint like so:
|
||||
|
||||
flint std.lnt -w1 project.lnt
|
||||
|
||||
When all syntax errors are resolved, you can begin turning on Warning
|
||||
messages (i.e., those listed in section 17.4 of the Lint manual). You can
|
||||
turn them on individually after '-w1' or you can instead use '-w2' and
|
||||
then suppress the Warnings that are less severe. (For details on message
|
||||
suppression, see section 5.2 of the Lint manual.)
|
||||
|
||||
At this point, you should be well-equipped to Lint any C program compiled
|
||||
with GCC. However, C++ users have a couple more points to consider.
|
||||
|
||||
The command used to invoke GCC also affects the set of predefined macros.
|
||||
Observe the difference in '#define' output when you invoke:
|
||||
|
||||
g++ -O3 -E -dM empty.c >lint_cppmac.h
|
||||
diff lint_cmac.h lint_cppmac.h
|
||||
|
||||
Also, note that the list of directories to search for Standard Library
|
||||
headers has some new additions when you use 'g++ -v -c empty.c' instead of
|
||||
'gcc -v -c empty.c'. Your sequence of --i options should be set
|
||||
accordingly.
|
||||
|
||||
That's about it for the preprocessor.
|
||||
|
||||
--- Size options ---
|
||||
|
||||
Finally, you'll need to establish sizes of primitive types. E.g. for a
|
||||
64-bit platform this includes setting '-sp8' (indicating that pointers are
|
||||
8 bytes wide). It often also involves setting '-sl8' (indicating that
|
||||
'long' is eight bytes wide). As suggested earlier, the makefile
|
||||
co-gcc.mak can generate these options for you.
|
||||
|
||||
If you find this tutorial to be lacking in some way, please contact us
|
||||
(support@gimpel.com) with your suggestions for improvement.
|
|
@ -0,0 +1,250 @@
|
|||
#define __DBL_MIN_EXP__ (-1021)
|
||||
#define __UINT_LEAST16_MAX__ 0xffff
|
||||
#define __ATOMIC_ACQUIRE 2
|
||||
#define __FLT_MIN__ 1.17549435082228750797e-38F
|
||||
#define __GCC_IEC_559_COMPLEX 2
|
||||
#define __UINT_LEAST8_TYPE__ unsigned char
|
||||
#define __SIZEOF_FLOAT80__ 16
|
||||
#define __INTMAX_C(c) c ## L
|
||||
#define __CHAR_BIT__ 8
|
||||
#define __UINT8_MAX__ 0xff
|
||||
#define __WINT_MAX__ 0xffffffffU
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#define __SIZE_MAX__ 0xffffffffffffffffUL
|
||||
#define __WCHAR_MAX__ 0x7fffffff
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
|
||||
#define __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L)
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
|
||||
#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
|
||||
#define __GCC_IEC_559 2
|
||||
#define __FLT_EVAL_METHOD__ 0
|
||||
#define __unix__ 1
|
||||
#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||
#define __x86_64 1
|
||||
#define __UINT_FAST64_MAX__ 0xffffffffffffffffUL
|
||||
#define __SIG_ATOMIC_TYPE__ int
|
||||
#define __DBL_MIN_10_EXP__ (-307)
|
||||
#define __FINITE_MATH_ONLY__ 0
|
||||
#define __GNUC_PATCHLEVEL__ 1
|
||||
#define __UINT_FAST8_MAX__ 0xff
|
||||
#define __has_include(STR) __has_include__(STR)
|
||||
#define __DEC64_MAX_EXP__ 385
|
||||
#define __INT8_C(c) c
|
||||
#define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL
|
||||
#define __SHRT_MAX__ 0x7fff
|
||||
#define __LDBL_MAX__ 1.18973149535723176502e+4932L
|
||||
#define __UINT_LEAST8_MAX__ 0xff
|
||||
#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
|
||||
#define __UINTMAX_TYPE__ long unsigned int
|
||||
#define __linux 1
|
||||
#define __DEC32_EPSILON__ 1E-6DF
|
||||
#define __unix 1
|
||||
#define __UINT32_MAX__ 0xffffffffU
|
||||
#define __LDBL_MAX_EXP__ 16384
|
||||
#define __WINT_MIN__ 0U
|
||||
#define __linux__ 1
|
||||
#define __SCHAR_MAX__ 0x7f
|
||||
#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
|
||||
#define __INT64_C(c) c ## L
|
||||
#define __DBL_DIG__ 15
|
||||
#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
|
||||
#define __SIZEOF_INT__ 4
|
||||
#define __SIZEOF_POINTER__ 8
|
||||
#define __USER_LABEL_PREFIX__
|
||||
#define __STDC_HOSTED__ 1
|
||||
#define __LDBL_HAS_INFINITY__ 1
|
||||
#define __FLT_EPSILON__ 1.19209289550781250000e-7F
|
||||
#define __LDBL_MIN__ 3.36210314311209350626e-4932L
|
||||
#define __STDC_UTF_16__ 1
|
||||
#define __DEC32_MAX__ 9.999999E96DF
|
||||
#define __INT32_MAX__ 0x7fffffff
|
||||
#define __SIZEOF_LONG__ 8
|
||||
#define __STDC_IEC_559__ 1
|
||||
#define __STDC_ISO_10646__ 201505L
|
||||
#define __UINT16_C(c) c
|
||||
#define __DECIMAL_DIG__ 21
|
||||
#define __gnu_linux__ 1
|
||||
#define __has_include_next(STR) __has_include_next__(STR)
|
||||
#define __LDBL_HAS_QUIET_NAN__ 1
|
||||
#define __GNUC__ 6
|
||||
#define __MMX__ 1
|
||||
#define __FLT_HAS_DENORM__ 1
|
||||
#define __SIZEOF_LONG_DOUBLE__ 16
|
||||
#define __BIGGEST_ALIGNMENT__ 16
|
||||
#define __DBL_MAX__ ((double)1.79769313486231570815e+308L)
|
||||
#define __INT_FAST32_MAX__ 0x7fffffffffffffffL
|
||||
#define __DBL_HAS_INFINITY__ 1
|
||||
#define __DEC32_MIN_EXP__ (-94)
|
||||
#define __INT_FAST16_TYPE__ long int
|
||||
#define __LDBL_HAS_DENORM__ 1
|
||||
#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
|
||||
#define __INT_LEAST32_MAX__ 0x7fffffff
|
||||
#define __DEC32_MIN__ 1E-95DF
|
||||
#define __DBL_MAX_EXP__ 1024
|
||||
#define __DEC128_EPSILON__ 1E-33DL
|
||||
#define __SSE2_MATH__ 1
|
||||
#define __ATOMIC_HLE_RELEASE 131072
|
||||
#define __PTRDIFF_MAX__ 0x7fffffffffffffffL
|
||||
#define __amd64 1
|
||||
#define __STDC_NO_THREADS__ 1
|
||||
#define __ATOMIC_HLE_ACQUIRE 65536
|
||||
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
|
||||
#define __SIZEOF_SIZE_T__ 8
|
||||
#define __SIZEOF_WINT_T__ 4
|
||||
#define __GCC_HAVE_DWARF2_CFI_ASM 1
|
||||
#define __GXX_ABI_VERSION 1010
|
||||
#define __FLT_MIN_EXP__ (-125)
|
||||
#define __INT_FAST64_TYPE__ long int
|
||||
#define __DBL_MIN__ ((double)2.22507385850720138309e-308L)
|
||||
#define __LP64__ 1
|
||||
#define __DECIMAL_BID_FORMAT__ 1
|
||||
#define __DEC128_MIN__ 1E-6143DL
|
||||
#define __REGISTER_PREFIX__
|
||||
#define __UINT16_MAX__ 0xffff
|
||||
#define __DBL_HAS_DENORM__ 1
|
||||
#define __UINT8_TYPE__ unsigned char
|
||||
#define __NO_INLINE__ 1
|
||||
#define __FLT_MANT_DIG__ 24
|
||||
#define __VERSION__ "6.3.1 20170306"
|
||||
#define __UINT64_C(c) c ## UL
|
||||
#define _STDC_PREDEF_H 1
|
||||
#define __GCC_ATOMIC_INT_LOCK_FREE 2
|
||||
#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __STDC_IEC_559_COMPLEX__ 1
|
||||
#define __INT32_C(c) c
|
||||
#define __DEC64_EPSILON__ 1E-15DD
|
||||
#define __ORDER_PDP_ENDIAN__ 3412
|
||||
#define __DEC128_MIN_EXP__ (-6142)
|
||||
#define __INT_FAST32_TYPE__ long int
|
||||
#define __UINT_LEAST16_TYPE__ short unsigned int
|
||||
#define unix 1
|
||||
#define __INT16_MAX__ 0x7fff
|
||||
#define __SIZE_TYPE__ long unsigned int
|
||||
#define __UINT64_MAX__ 0xffffffffffffffffUL
|
||||
#define __INT8_TYPE__ signed char
|
||||
#define __ELF__ 1
|
||||
#define __GCC_ASM_FLAG_OUTPUTS__ 1
|
||||
#define __FLT_RADIX__ 2
|
||||
#define __INT_LEAST16_TYPE__ short int
|
||||
#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
|
||||
#define __UINTMAX_C(c) c ## UL
|
||||
#define __SSE_MATH__ 1
|
||||
#define __k8 1
|
||||
#define __SIG_ATOMIC_MAX__ 0x7fffffff
|
||||
#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||
#define __SIZEOF_PTRDIFF_T__ 8
|
||||
#define __x86_64__ 1
|
||||
#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
|
||||
#define __INT_FAST16_MAX__ 0x7fffffffffffffffL
|
||||
#define __UINT_FAST32_MAX__ 0xffffffffffffffffUL
|
||||
#define __UINT_LEAST64_TYPE__ long unsigned int
|
||||
#define __FLT_HAS_QUIET_NAN__ 1
|
||||
#define __FLT_MAX_10_EXP__ 38
|
||||
#define __LONG_MAX__ 0x7fffffffffffffffL
|
||||
#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
|
||||
#define __FLT_HAS_INFINITY__ 1
|
||||
#define __UINT_FAST16_TYPE__ long unsigned int
|
||||
#define __DEC64_MAX__ 9.999999999999999E384DD
|
||||
#define __CHAR16_TYPE__ short unsigned int
|
||||
#define __PRAGMA_REDEFINE_EXTNAME 1
|
||||
#define __SEG_FS 1
|
||||
#define __INT_LEAST16_MAX__ 0x7fff
|
||||
#define __DEC64_MANT_DIG__ 16
|
||||
#define __INT64_MAX__ 0x7fffffffffffffffL
|
||||
#define __UINT_LEAST32_MAX__ 0xffffffffU
|
||||
#define __SEG_GS 1
|
||||
#define __GCC_ATOMIC_LONG_LOCK_FREE 2
|
||||
#define __INT_LEAST64_TYPE__ long int
|
||||
#define __INT16_TYPE__ short int
|
||||
#define __INT_LEAST8_TYPE__ signed char
|
||||
#define __STDC_VERSION__ 201112L
|
||||
#define __DEC32_MAX_EXP__ 97
|
||||
#define __INT_FAST8_MAX__ 0x7f
|
||||
#define __INTPTR_MAX__ 0x7fffffffffffffffL
|
||||
#define linux 1
|
||||
#define __SSE2__ 1
|
||||
#define __LDBL_MANT_DIG__ 64
|
||||
#define __DBL_HAS_QUIET_NAN__ 1
|
||||
#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
|
||||
#define __code_model_small__ 1
|
||||
#define __k8__ 1
|
||||
#define __INTPTR_TYPE__ long int
|
||||
#define __UINT16_TYPE__ short unsigned int
|
||||
#define __WCHAR_TYPE__ int
|
||||
#define __SIZEOF_FLOAT__ 4
|
||||
#define __UINTPTR_MAX__ 0xffffffffffffffffUL
|
||||
#define __DEC64_MIN_EXP__ (-382)
|
||||
#define __INT_FAST64_MAX__ 0x7fffffffffffffffL
|
||||
#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
|
||||
#define __FLT_DIG__ 6
|
||||
#define __UINT_FAST64_TYPE__ long unsigned int
|
||||
#define __INT_MAX__ 0x7fffffff
|
||||
#define __amd64__ 1
|
||||
#define __INT64_TYPE__ long int
|
||||
#define __FLT_MAX_EXP__ 128
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#define __DBL_MANT_DIG__ 53
|
||||
#define __SIZEOF_FLOAT128__ 16
|
||||
#define __INT_LEAST64_MAX__ 0x7fffffffffffffffL
|
||||
#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||
#define __DEC64_MIN__ 1E-383DD
|
||||
#define __WINT_TYPE__ unsigned int
|
||||
#define __UINT_LEAST32_TYPE__ unsigned int
|
||||
#define __SIZEOF_SHORT__ 2
|
||||
#define __SSE__ 1
|
||||
#define __LDBL_MIN_EXP__ (-16381)
|
||||
#define __INT_LEAST8_MAX__ 0x7f
|
||||
#define __SIZEOF_INT128__ 16
|
||||
#define __LDBL_MAX_10_EXP__ 4932
|
||||
#define __ATOMIC_RELAXED 0
|
||||
#define __DBL_EPSILON__ ((double)2.22044604925031308085e-16L)
|
||||
#define _LP64 1
|
||||
#define __UINT8_C(c) c
|
||||
#define __INT_LEAST32_TYPE__ int
|
||||
#define __SIZEOF_WCHAR_T__ 4
|
||||
#define __UINT64_TYPE__ long unsigned int
|
||||
#define __INT_FAST8_TYPE__ signed char
|
||||
#define __GNUC_STDC_INLINE__ 1
|
||||
#define __DBL_DECIMAL_DIG__ 17
|
||||
#define __STDC_UTF_32__ 1
|
||||
#define __FXSR__ 1
|
||||
#define __DEC_EVAL_METHOD__ 2
|
||||
#define __UINT32_C(c) c ## U
|
||||
#define __INTMAX_MAX__ 0x7fffffffffffffffL
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __FLT_DENORM_MIN__ 1.40129846432481707092e-45F
|
||||
#define __INT8_MAX__ 0x7f
|
||||
#define __UINT_FAST32_TYPE__ long unsigned int
|
||||
#define __CHAR32_TYPE__ unsigned int
|
||||
#define __FLT_MAX__ 3.40282346638528859812e+38F
|
||||
#define __INT32_TYPE__ int
|
||||
#define __SIZEOF_DOUBLE__ 8
|
||||
#define __FLT_MIN_10_EXP__ (-37)
|
||||
#define __INTMAX_TYPE__ long int
|
||||
#define __DEC128_MAX_EXP__ 6145
|
||||
#define __ATOMIC_CONSUME 1
|
||||
#define __GNUC_MINOR__ 3
|
||||
#define __UINTMAX_MAX__ 0xffffffffffffffffUL
|
||||
#define __DEC32_MANT_DIG__ 7
|
||||
#define __DBL_MAX_10_EXP__ 308
|
||||
#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
|
||||
#define __INT16_C(c) c
|
||||
#define __STDC__ 1
|
||||
#define __PTRDIFF_TYPE__ long int
|
||||
#define __ATOMIC_SEQ_CST 5
|
||||
#define __UINT32_TYPE__ unsigned int
|
||||
#define __UINTPTR_TYPE__ long unsigned int
|
||||
#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
|
||||
#define __DEC128_MANT_DIG__ 34
|
||||
#define __LDBL_MIN_10_EXP__ (-4931)
|
||||
#define __SIZEOF_LONG_LONG__ 8
|
||||
#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
|
||||
#define __LDBL_DIG__ 18
|
||||
#define __FLT_DECIMAL_DIG__ 9
|
||||
#define __UINT_FAST16_MAX__ 0xffffffffffffffffUL
|
||||
#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
|
||||
#define __UINT_FAST8_TYPE__ unsigned char
|
||||
#define __ATOMIC_ACQ_REL 4
|
||||
#define __ATOMIC_RELEASE 3
|
|
@ -0,0 +1,85 @@
|
|||
# This file contains functions and configurations for generating PC-Lint build
|
||||
# targets for your CMake projects.
|
||||
|
||||
set(PC_LINT_EXECUTABLE "lint-nt.exe" CACHE STRING "full path to the pc-lint executable. NOT the generated lin.bat")
|
||||
set(PC_LINT_CONFIG_DIR "${PROJECT_SOURCE_DIR}/lint/gnu" CACHE STRING "full path to the directory containing pc-lint configuration files")
|
||||
set(PC_LINT_USER_FLAGS "-b" CACHE STRING "additional pc-lint command line options -- some flags of pc-lint cannot be set in option files (most notably -b)")
|
||||
|
||||
# a phony target which causes all available *_LINT targets to be executed
|
||||
add_custom_target(ALL_LINT)
|
||||
|
||||
# add_pc_lint(target source1 [source2 ...])
|
||||
#
|
||||
# Takes a list of source files and generates a build target which can be used
|
||||
# for linting all files
|
||||
#
|
||||
# The generated lint commands assume that a top-level config file named
|
||||
# 'std.lnt' resides in the configuration directory 'PC_LINT_CONFIG_DIR'. This
|
||||
# config file must include all other config files. This is standard lint
|
||||
# behaviour.
|
||||
#
|
||||
# Parameters:
|
||||
# - target: the name of the target to which the sources belong. You will get a
|
||||
# new build target named ${target}_LINT
|
||||
# - source1 ... : a list of source files to be linted. Just pass the same list
|
||||
# as you passed for add_executable or add_library. Everything except
|
||||
# C and CPP files (*.c, *.cpp, *.cxx) will be filtered out.
|
||||
#
|
||||
# Example:
|
||||
# If you have a CMakeLists.txt which generates an executable like this:
|
||||
#
|
||||
# set(MAIN_SOURCES main.c foo.c bar.c)
|
||||
# add_executable(main ${MAIN_SOURCES})
|
||||
#
|
||||
# include this file
|
||||
#
|
||||
# include(/path/to/pc_lint.cmake)
|
||||
#
|
||||
# and add a line to generate the main_LINT target
|
||||
#
|
||||
# if(COMMAND add_pc_lint)
|
||||
# add_pc_lint(main ${MAIN_SOURCES})
|
||||
# endif(COMMAND add_pc_lint)
|
||||
#
|
||||
function(add_pc_lint target)
|
||||
get_directory_property(lint_include_directories INCLUDE_DIRECTORIES)
|
||||
get_directory_property(lint_defines COMPILE_DEFINITIONS)
|
||||
|
||||
# let's get those elephants across the alps
|
||||
# prepend each include directory with "-i"; also quotes the directory
|
||||
set(lint_include_directories_transformed)
|
||||
foreach(include_dir ${lint_include_directories})
|
||||
list(APPEND lint_include_directories_transformed -i"${include_dir}")
|
||||
endforeach(include_dir)
|
||||
|
||||
# prepend each definition with "-d"
|
||||
set(lint_defines_transformed)
|
||||
foreach(definition ${lint_defines})
|
||||
list(APPEND lint_defines_transformed -d${definition})
|
||||
endforeach(definition)
|
||||
|
||||
# list of all commands, one for each given source file
|
||||
set(pc_lint_commands)
|
||||
|
||||
foreach(sourcefile ${ARGN})
|
||||
# only include c and cpp files
|
||||
if( sourcefile MATCHES \\.c$|\\.cxx$|\\.cpp$ )
|
||||
# make filename absolute
|
||||
get_filename_component(sourcefile_abs ${sourcefile} ABSOLUTE)
|
||||
# create command line for linting one source file and add it to the list of commands
|
||||
list(APPEND pc_lint_commands
|
||||
COMMAND ${PC_LINT_EXECUTABLE}
|
||||
-i"${PC_LINT_CONFIG_DIR}" std.lnt
|
||||
"-u" ${PC_LINT_USER_FLAGS}
|
||||
${lint_include_directories_transformed}
|
||||
${lint_defines_transformed}
|
||||
${sourcefile_abs})
|
||||
endif()
|
||||
endforeach(sourcefile)
|
||||
|
||||
# add a custom target consisting of all the commands generated above
|
||||
add_custom_target(${target}_LINT ${pc_lint_commands} VERBATIM)
|
||||
# make the ALL_LINT target depend on each and every *_LINT target
|
||||
add_dependencies(ALL_LINT ${target}_LINT)
|
||||
|
||||
endfunction(add_pc_lint)
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
co-gcc.lnt
|
|
@ -0,0 +1,42 @@
|
|||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifndef LINT_SUPPORT_CO_MSC100_H_
|
||||
#define LINT_SUPPORT_CO_MSC100_H_
|
||||
|
||||
// co-msc100.h --
|
||||
// This header is automatically included in every module if you use
|
||||
// co-msc100.lnt. (There is a -header(co-msc100.h) option therein
|
||||
// for this purpose.)
|
||||
|
||||
// Microsoft's C++11 implementation does not yet include built-in support
|
||||
// for the new character types, so we need to disable the relevant
|
||||
// keywords here. (This must be done before the inclusion of any other
|
||||
// header file because Microsoft's library headers contain declarations of
|
||||
// typedef names with the same spelling.)
|
||||
//lint -rw(char16_t,char32_t)
|
||||
|
||||
// Next we must compensate for the fact that class typeinfo is available
|
||||
// for use in the MSC compilers without an explicit definition. According
|
||||
// to the standard this class definition is not (available by default).
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#else // C mode
|
||||
|
||||
// co-msc100.lnt defines some macros that the Microsoft compiler defines
|
||||
// in C++ modes but not in C mode; we must un-define them here:
|
||||
#undef _CPPRTTI
|
||||
#undef _NATIVE_WCHAR_T_DEFINED
|
||||
#undef _WCHAR_T_DEFINED
|
||||
#undef _NATIVE_NULLPTR_SUPPORTED
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* LINT_SUPPORT_CO_MSC100_H_ */
|
|
@ -0,0 +1,459 @@
|
|||
/* Date Stamp */ -d"_lint_co_msc100_lnt=co-msc100.lnt modified 19-Sep-2013"
|
||||
/* To document usage use: -message( "Using " _lint_co_msc100_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
// co-msc100.lnt
|
||||
// Compiler Options for Visual Studio for C/C++ Version 10.00
|
||||
// (Visual Studio 2010)
|
||||
// This file contains options to allow PC-lint to process source
|
||||
// files for your compiler. It is used as follows:
|
||||
//
|
||||
// lint co-msc100.lnt source-file(s)
|
||||
//
|
||||
// (See macros-msc.c and/or macros-msc.cpp for details.)
|
||||
|
||||
// Section 1: options independent of the use of the automatic macro
|
||||
// generator (macros-msc.cpp)
|
||||
//
|
||||
-cmsc
|
||||
-A(C++2011)
|
||||
+compiler(search_actively_including_stack)
|
||||
-si4 // integers are 4 bytes
|
||||
-sp4 // pointers are 4 bytes too.
|
||||
|
||||
// We now support __declspec directly so that the following
|
||||
// option is now commented out. If trouble ensues you can
|
||||
// once again disable __declspec through this option.
|
||||
// -d__declspec()= // ignore this construct
|
||||
-d_declspec=__declspec // the single '_' version is occasionally used
|
||||
|
||||
// while processing compiler (library) header files ...
|
||||
-wlib(1) // sets the warning level within library headers to 1
|
||||
// (no warnings, just syntax errors). Comment out if you
|
||||
// are actually linting library headers. This
|
||||
// option makes obsolete options of the form -elib(axxx) where
|
||||
// xxx >= 400 which may be retained for historical reasons.
|
||||
-elib(1111) // Some VC++ headers contain explicit specializations at class
|
||||
// scope.
|
||||
-elib(19) // useless declarations (lone semicolons)
|
||||
-elib(123) // function-like macro name used as non macro
|
||||
-elib(652) // suppress message about #define of earlier declared symbols
|
||||
-elib(762) // suppress message about multiple identical declarations and
|
||||
-elib(760) // suppress message about multiple identical macro defs
|
||||
-elib(514) // allow #if <boolean> | <boolean>
|
||||
-elib(553) // undefined preprocessor variables assumed 0
|
||||
-elib(1081) // suspicious object argument to an object parameter
|
||||
-elib(726) // extraneous comma in enum definition
|
||||
|
||||
// SREGS, WORDREGS, BYTEREGS are defined in both bios.h and dos.h
|
||||
// and accordingly you MAY get type differences based on 'origin'.
|
||||
// If so, use the following options:
|
||||
// -etd(origin)
|
||||
// -elib(770)
|
||||
|
||||
-format=%(%f(%l)\s:\s%)%t\s%n:\s%m
|
||||
// error format similar to MSC
|
||||
// Note that %c can also be used to specify column
|
||||
-e46 // allows bit-fields to be other than int or unsigned
|
||||
+fan // allow anonymous unions
|
||||
+fdi // Use directory of the including file
|
||||
+fbo // enable the bool type
|
||||
+fwm // wprintf format codes are not standard
|
||||
-fdh // do not append a .h to header names
|
||||
-esym(123,min,max) // allows users to use min, max as variables
|
||||
+rw(__inline) // activate the __inline keyword
|
||||
-rw_asgn(__nullptr,nullptr)
|
||||
-e19 // Suppress errors about lone semicolons
|
||||
+ppw(import) // activate #import
|
||||
-d_inline=__inline // _inline is the same as __inline
|
||||
-sld8 // sizeof(long double) is 8.
|
||||
-function(exit,_exit) // _exit() is like exit()
|
||||
-function(exit,_assert) // _assert() is like exit()
|
||||
-emacro(506,assert) // don't warn about constant value Boolean
|
||||
-emacro(734,putc) // don't complain about items being too large.
|
||||
-emacro(415,_FP_SEG) // access of out-of-bounds pointer
|
||||
-emacro(740,FP_SEG,FP_OFF) // unusual casts
|
||||
-emacro((???),va_arg) // the va_arg() macro can yield 415, 416, 661, 662
|
||||
// 796 and 797 (out-of-bounds errors).
|
||||
-emacro((???),va_start) // the same applies to va_start
|
||||
-emacro(413,offsetof) // use of NULL pointer creates a stir
|
||||
-emacro(545,offsetof) // addressing an array member is OK
|
||||
-emacro(845,RGB) // a common use of RGB uses a operator that produces a 0
|
||||
-e793 // inhibit 'ANSI limit reached' --
|
||||
// limits are impractically low with MSVC headers
|
||||
-esym(628,eof) // failure to provide argument information for eof()
|
||||
-esym(773,L_tmpnam) // defined with an unparenthesized '+'
|
||||
-esym(438,_acp) // USES_CONVERSION assigns to _acp.
|
||||
-emacro(571,__isascii) // don't warn about the unusual cast
|
||||
-emacro(522,UNREFERENCED_PARAMETER) // don't complain about a lack of
|
||||
// side-effects
|
||||
-emacro(648,CDN_*) // ignore unsigned overflow
|
||||
-emacro(648,OIVN_*) // ignore unsigned overflow
|
||||
-emacro(648,TTN_*) // ignore unsigned overflow
|
||||
-emacro(648,TVN_*) // ignore unsigned overflow
|
||||
-emacro(648,TBN_*) // ignore unsigned overflow
|
||||
|
||||
// The following functions exhibit variable return modes.
|
||||
// That is, they may equally-usefully be called for a value
|
||||
// as called just for their effects. Accordingly we inhibit
|
||||
// Warning 534 for these functions.
|
||||
// Feel free to add to or subtract from this list.
|
||||
|
||||
-esym(534,close,creat,fclose,fflush,_flsbuf,fprintf,fputc)
|
||||
-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)
|
||||
-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)
|
||||
-esym(534,strncat,strncpy,unlink,write)
|
||||
|
||||
// These are the wide char variants of printf-scanf family
|
||||
|
||||
-wprintf( 1, wprintf )
|
||||
-wprintf( 3, fwprintf, swprintf )
|
||||
-wscanf( 1, wscanf )
|
||||
-wscanf( 2, fwscanf, swscanf )
|
||||
|
||||
// These are substitutions for sprintf
|
||||
|
||||
-printf( 3, StringCbPrintfA )
|
||||
-printf( 3, StringCchPrintfA )
|
||||
-wprintf( 3, StringCbPrintfW )
|
||||
-wprintf( 3, StringCchPrintfW )
|
||||
|
||||
// The following options are used to adjust our function mimicry to
|
||||
// the actual library as provided by MS.
|
||||
|
||||
-function( wcstombs(1) ) // remove the check for a NULL first arg to wcstombs()
|
||||
|
||||
// The following options are required by most compilers to
|
||||
// noiselessly process iostream.h
|
||||
|
||||
-elib(1717) // empty prototypes
|
||||
-elib(522) // function return value ignored
|
||||
-elib(1053) // prototypes cannot be distinguished
|
||||
-elib(1721) // unusual operator =() declaration
|
||||
-elib(1720) // assignment op has non-const parameter
|
||||
-elib(655) // bitwise operator combining compatible enum's
|
||||
-elib(641) // converting enum's to int
|
||||
-elib(537) // repeated include file (ios.h)
|
||||
-elib(1511) // member (rdbuf) hides nonvirtual member
|
||||
-elib(1712) // default constructor not defined for class
|
||||
-elib(1736) // redundant access specifier
|
||||
-esym(1702,operator<<,operator>>) // both a member and an ordinary function
|
||||
|
||||
// These functions return things that are frequently ignored.
|
||||
|
||||
-esym(534,*operator<<,*operator>>)
|
||||
|
||||
// The following additional options seem to be needed.
|
||||
|
||||
-elib(506) // constant value Boolean
|
||||
-elib(620) // el or one? (some constants end in 'l' not 'L')
|
||||
-elib(648) // overflow in computing constant (3<<16)
|
||||
-elib(659) // nothing fold_NATIVE_WCHAR_T_DEFINEDlows '}' on some line
|
||||
-elib(723) // suspicious use of '='
|
||||
-elib(747) // significant prototype coercion
|
||||
-elib(740) // unusual pointer casts
|
||||
-elib(1007) // virtual functions within extern "C" block
|
||||
-elib(1029) // default argument repeated -- can't dist. char, signed char
|
||||
-elib(1055) // call to rdbuf() questioned?
|
||||
-elib(1504) // apparently useless structs
|
||||
-elib(1708,1709) // minor C/C++ declaration conflict
|
||||
-elib(1707) // operator new declared w/o 'static'
|
||||
-elib(1722) // assignment op does not return reference
|
||||
-elib(149) // default argument found in C code.
|
||||
-elib(578) // declaration of time hides delaration of global time().
|
||||
-elib(761) // two equivalent typedef declarations
|
||||
-elib(1065) // same name declared as "C" and not "C"
|
||||
-elib(1066) // same name declared as "C" and not "C"
|
||||
-elib(1704) // constructor with private access declaration
|
||||
-elib(1735) // default parameter within virtual function
|
||||
-elib(773) // macros that look like unparenthesized expressions
|
||||
-elib(806) // 1-bit bitfields typed int
|
||||
-elib(1501) // 0-length data members
|
||||
-elib(1510) // base class has no destructor
|
||||
-elib(1516) // data member hides inherited member
|
||||
-elib(1509) // base class destructor is not virtual
|
||||
|
||||
// Special Notice: You may be receiving mysterious 1058 errors
|
||||
// when you use "iomanipulator"s. For example:
|
||||
// cout << setw(4) << 4;
|
||||
// results in Error 1058 (assigning a const to a ref) because the
|
||||
// manipulator setw returns a non-lvalue which is assigned to a reference.
|
||||
// This reflects an oversight in the Microsoft header file: iomanip.h
|
||||
// Therein you may change the declaration:
|
||||
// friend ostream& operator<<(iostream& s, IOMANIP(T) & sm) { ...
|
||||
// to:
|
||||
// friend ostream& operator<<(iostream& s, const IOMANIP(T) & sm) { ...
|
||||
// to reflect the fact that sm is not modified by this function.
|
||||
|
||||
+fll // enable long long
|
||||
|
||||
// In the following option we define __uuidof() and suppress
|
||||
// Errors 50 and 69 and 1924 in exprs. containing same
|
||||
-d"__uuidof()= /*lint --e(50,69,1924) */ (_GUID)0"
|
||||
|
||||
-esym(123,FD_SET) // defined as macro and as typedef
|
||||
-esym(1726,endl,ends) // taking the address of an overloaded function
|
||||
-esym(18,Data_t::Data_t) // definition not matching declaration
|
||||
|
||||
-elib(10) // expecting ')' -- comdef.h has a: #if defined( id
|
||||
-elib(43) // vacuous array within _MIDL_FORMAT_STRING
|
||||
-elib(602) // benign comment within comment
|
||||
-elib(657) // declaring "anonymous struct" in union _LARGE_INTEGER
|
||||
-elib(799) // long numerical constant for max. __int64
|
||||
-elib(1502) // nothrow has no data members
|
||||
-elib(1505) // no access specifier in base class specifier
|
||||
-elib(1515) // AFX_THREAD_STATE member has no default constructor
|
||||
-elib(1706) // Unusual declaration with a scope operator
|
||||
-elib(1725) // data member is a reference
|
||||
-elib(1548) // conflicting exception specifications
|
||||
-elib(1737) // hiding global operator new
|
||||
-elib(1739) // binary operator should be non-member function
|
||||
-elib(1748) // non-virtual base class included twice
|
||||
-elib(1759) // post-fix operator returns a reference
|
||||
|
||||
// Add elements of ole automation
|
||||
|
||||
lib-ole.lnt
|
||||
|
||||
// Options required for .net
|
||||
|
||||
-d_stdcall=__stdcall // make _stdcall equivalent to __stdcall
|
||||
-d__interface=class // treat an interface the same as a class
|
||||
-d__unaligned= // pass over the __unaligned keyword
|
||||
-d__w64= // ignore this identifier
|
||||
-esym(40,DLGPROC) // used before being defined
|
||||
-elib(146) // assuming binary constant
|
||||
-elib(1015) // GetDefaultThreads not found in class
|
||||
+ppw(using) // ignore #using for now.
|
||||
|
||||
-d__pragma(x)= // ignore the pragma extension
|
||||
+rw(__ptr64) // additional qualifier
|
||||
+rw_asgn(__thiscall,fortran) // additional qualifier
|
||||
|
||||
-"d__identifier(x)=___identifier x"
|
||||
// treat C++ keyword x as an identifier
|
||||
|
||||
-elibsym(1512) // base class destructor not virtual
|
||||
|
||||
-d__TIMESTAMP__="Mon Jan 01 00:00:00 2010"
|
||||
-d__COUNTER__=__lint__COUNTER__
|
||||
-d__FUNCDNAME__="MyFunc"
|
||||
-d__FUNCSIG__="MyFunc"
|
||||
-d__FUNCTION__=___function___
|
||||
|
||||
-dinitonly= // Compiler should catch miss-uses.
|
||||
// Lint can just skip over it.
|
||||
-"dliteral=static const" // Documentation says they are
|
||||
// equivalent for member data.
|
||||
|
||||
// __try_cast is like dynamic_cast (except the former throws where
|
||||
// the latter returns 0).
|
||||
|
||||
-d__try_cast=dynamic_cast
|
||||
|
||||
+rw(__restrict) // reserved word
|
||||
|
||||
// Partial support for the "old" (VC++ 2003) Managed Extensions
|
||||
// syntax:
|
||||
+rw( __gc, __value, __nogc, __pin, __ptr32, __ptr64 )
|
||||
|
||||
-$ // $ can be used in identifiers
|
||||
+rw( __allowed_on_parameter )
|
||||
+rw( __allowed_on_function )
|
||||
+rw( __allowed_on_typedecl )
|
||||
+rw( __allowed_on_return )
|
||||
+rw( __allowed_on_struct )
|
||||
+rw( __allowed_on_function_or_typedecl )
|
||||
+rw( __allowed_on_field )
|
||||
+rw( __allowed_on_parameter_or_return )
|
||||
+rw( __allowed_on_function )
|
||||
+rw( *type_traits ) //type traits support
|
||||
|
||||
+e1942 // This Elective Note alerts the user to the non-standard
|
||||
// way in which MS handles originally-dependent base classes.
|
||||
// E.g. template<class T> class A : T { ... x ... };
|
||||
// Should T be searched for "x" during instantiation?
|
||||
// the standard says "no", MS does.
|
||||
|
||||
|
||||
-header(co-msc100.h) // implicitly includes <typeinfo>. (Needed because
|
||||
// MSVC 9 implicitly declares class type_info.)
|
||||
|
||||
|
||||
// Section 2: options that should be commented out if you use the
|
||||
// automatic macro generator (macros-msc.cpp)
|
||||
|
||||
// Note, a macro option of the form:
|
||||
// -dA{1}
|
||||
// has the same effect as:
|
||||
// -dA=1
|
||||
// or:
|
||||
// -d"A=1"
|
||||
// The curly-brace version of the syntax is appropriate for
|
||||
// macro-scavenging (the method we used to generate the macro options
|
||||
// below). For details, see notes on the -scavenge() option in section
|
||||
// 5.8.3 in the Lint manual. See also the macro generator file,
|
||||
// macros-msc.cpp, which follows the form of -scavenge() output.
|
||||
|
||||
// We generated the options in this section with the following commands:
|
||||
// %VSInstallDir%\vc\bin\vcvars32.bat
|
||||
// cl /EP /C macros-msc.cpp
|
||||
// The options for other build configurations will probably differ (which
|
||||
// is why you should comment out the following if you use the macro
|
||||
// generator).
|
||||
|
||||
// Also note: some of the following are defined for C++ mode but not for C
|
||||
// mode; but there's no need to comment them out here because they are
|
||||
// conditionally #undef'd in co-msc100.h.
|
||||
|
||||
-d_CPPRTTI{1}
|
||||
//
|
||||
// Defined for code compiled with /GR (Enable Run-Time Type
|
||||
// Information).
|
||||
//
|
||||
|
||||
-d_INTEGRAL_MAX_BITS{64}
|
||||
//
|
||||
// Reports the maximum size (in bits) for an integral type.
|
||||
//
|
||||
|
||||
// NOTE:
|
||||
// When generating 64-bit code, the definition for _M_IX86 must be
|
||||
// commented out.
|
||||
-d_M_IX86{600}
|
||||
//
|
||||
// Defined for x86 processors. See the "Values for _M_IX86 table" (in
|
||||
// Microsoft's preprocessor documentation) for more information. This
|
||||
// is not defined for x64 processors.
|
||||
//
|
||||
|
||||
-d_M_IX86_FP{0}
|
||||
//
|
||||
// Expands to a value indicating which /arch compiler option was used:
|
||||
//
|
||||
// 0 if /arch was not used.
|
||||
//
|
||||
// 1 if /arch:SSE was used.
|
||||
//
|
||||
// 2 if /arch:SSE2 was used.
|
||||
//
|
||||
// See /arch (Minimum CPU Architecture) for more information.
|
||||
//
|
||||
|
||||
-d_MSC_BUILD{1}
|
||||
//
|
||||
// Evaluates to the revision number component of the compiler's
|
||||
// version number. The revision number is the fourth component of the
|
||||
// period-delimited version number. For example, if the version number
|
||||
// of the Visual C++ compiler is 15.00.20706.01, the _MSC_BUILD macro
|
||||
// evaluates to 1.
|
||||
//
|
||||
|
||||
-d_MSC_EXTENSIONS{1}
|
||||
//
|
||||
// This macro is defined when you compile with the /Ze compiler option
|
||||
// (the default). Its value, when defined, is 1.
|
||||
//
|
||||
|
||||
-d_MSC_FULL_VER{160030319}
|
||||
//
|
||||
// Evaluates to the major, minor, and build number components of the
|
||||
// compiler's version number. The major number is the first component
|
||||
// of the period-delimited version number, the minor number is the
|
||||
// second component, and the build number is the third component. For
|
||||
// example, if the version number of the Visual C++ compiler is
|
||||
// 15.00.20706.01, the _MSC_FULL_VER macro evaluates to 150020706.
|
||||
// Type cl /? at the command line to view the compiler's version
|
||||
// number.
|
||||
//
|
||||
|
||||
-d_MSC_VER{1600}
|
||||
//
|
||||
// Evaluates to the major and minor number components of the
|
||||
// compiler's version number. The major number is the first component
|
||||
// of the period-delimited version number and the minor number is the
|
||||
// second component.
|
||||
//
|
||||
// For example, if the version number of the Visual C++ compiler is
|
||||
// 15.00.20706.01, the _MSC_VER macro evaluates to 1500.
|
||||
//
|
||||
// In Visual Studio 2010, _MSC_VER is defined as 1600.
|
||||
//
|
||||
|
||||
-d_MT{1}
|
||||
//
|
||||
// Defined when /MD or /MDd (Multithreaded DLL) or /MT or /MTd
|
||||
// (Multithreaded) is specified.
|
||||
//
|
||||
|
||||
-d_NATIVE_WCHAR_T_DEFINED{1}
|
||||
//
|
||||
// Defined when /Zc:wchar_t is used.
|
||||
//
|
||||
|
||||
-d_WCHAR_T_DEFINED{1}
|
||||
//
|
||||
// Defined when /Zc:wchar_t is used or if wchar_t is defined in a
|
||||
// system header file included in your project.
|
||||
//
|
||||
|
||||
-d_WIN32{1}
|
||||
//
|
||||
// Defined for applications for Win32 and Win64. Always defined.
|
||||
//
|
||||
|
||||
/**** Undocumented predefined macros follow ****/
|
||||
|
||||
-d_NATIVE_NULLPTR_SUPPORTED{1}
|
||||
|
||||
// Section 3: options that should remain commented out if you use the
|
||||
// automatic macro generator (macros-msc.cpp)
|
||||
|
||||
// When compiling with /J, use:
|
||||
//+fcu // Plain char is unsigned
|
||||
//-d_CHAR_UNSIGNED
|
||||
|
||||
// When compiling with /clr, /clr:pure or /clr:safe, use:
|
||||
//-d__cplusplus_cli=200406 // for all 3
|
||||
//-d_M_CEE_PURE // for /clr:pure
|
||||
//-d_M_CEE_SAFE // for /clr:safe
|
||||
//-d_MANAGED // for /clr
|
||||
|
||||
// When using any /clr form, use:
|
||||
//-d_M_CEE
|
||||
|
||||
|
||||
// When compiling with /GX or /EH, use:
|
||||
//-d_CPPUNWIND // Enable Exception Handling
|
||||
|
||||
// When compiling for Win64, use:
|
||||
//-d_WIN64
|
||||
|
||||
// When compiling with /Wp64, use:
|
||||
//-d_Wp64 // 64-bit portability
|
||||
|
||||
// Be sure to define your platform if any of the following apply:
|
||||
//-d_M_ALPHA // For DEC ALPHA platforms
|
||||
//-d_M_IA64 // For Itanium 64-bit processors
|
||||
//-d_M_X64 // For x64 processors
|
||||
|
||||
// When compiling with the /RTC option, use:
|
||||
//-d__MSVC_RUNTIME_CHECKS // Using such checks
|
||||
|
||||
// When compiling with /openmp, use:
|
||||
//-d_OPENMP=200203 // OpenMP specification date
|
||||
|
||||
// When compiling with /Zl, use:
|
||||
//-d_VC_NODEFAULTLIB // Omit default library name in *.obj file
|
||||
|
||||
/* DLL's or Multithreads? Enable the following:
|
||||
|
||||
-d_AFXDLL // making a DLL
|
||||
-d_DLL // ditto
|
||||
|
||||
*/
|
|
@ -0,0 +1,221 @@
|
|||
/* Date Stamp */ -d"_lint_env_vc10_lnt=env-vc10.lnt modified 22-Feb-2012"
|
||||
/* To document usage use: -message( "Using " _lint_env_vc10_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
/*
|
||||
env-vc10.lnt: environment parameters for Microsoft's Visual C++ 10.0
|
||||
|
||||
If you are using Microsoft Visual Studio 2010 and you wish to invoke
|
||||
PC-lint from that environment then add one or more commands to the
|
||||
Tools menu as follows.
|
||||
|
||||
Simple Check
|
||||
------------
|
||||
|
||||
For example, to add a simple facility to lint the current file you
|
||||
may do the following:
|
||||
|
||||
1. From the Tools Menu choose "External Tools ..."
|
||||
2. Click the "Add" button.
|
||||
3. You will now be able to enter the fields of this Tool.
|
||||
Modify them so that they approximate the following:
|
||||
|
||||
Title: PC-lint (Simple Check)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments:
|
||||
-i"c:\lint" std.lnt env-vc10.lnt "$(ItemFileName)$(ItemExt)"
|
||||
Initial Directory: $(ItemDir)
|
||||
|
||||
X_Use Output Window __Prompt for arguments __Close on exit
|
||||
|
||||
Please note that you will have to change the "Command:" path if
|
||||
the PC-lint Installation Directory is anything other than c:\lint
|
||||
and you will have to change the "Arguments:" line if the
|
||||
Configuration Directory is anything other than c:\lint
|
||||
|
||||
4. Select OK to return to the main environment.
|
||||
|
||||
This will result in the Tools menu containing the additional item
|
||||
"PC-lint (Simple Check)". Checking 'X' on 'Use Output Window' is
|
||||
important because in this way you can advance from error to error
|
||||
using the F8 key (Shift F8 to reverse).
|
||||
|
||||
Strings of the form $(...) are called macros and can be typed in
|
||||
directly as shown or can be selected from a menu by clicking
|
||||
a right arrow in the dialog box. $(ItemFileName) refers to the
|
||||
file name of the currently edited file without its path and without
|
||||
its extension. $(ItemExt) is its extension. $(ItemDir) represents
|
||||
the file's directory.
|
||||
|
||||
You will probably want to advance your new tool upward into the
|
||||
initial position of all tools while you are testing and modifying the
|
||||
command. You can do this by using the "Move Up" button that appears
|
||||
on the External Tools dialog.
|
||||
|
||||
The benefits of using "Initial Directory" are that file-names in lint
|
||||
error messages will not be so long, and, also, this directory can
|
||||
contain a std.lnt that overrides the global std.lnt in the
|
||||
Configuration Directory.
|
||||
|
||||
This Simple Check is fine to check stand-alone modules but to check
|
||||
projects or to unit check modules that are in projects we need to
|
||||
go a bit further ...
|
||||
|
||||
Project Creation
|
||||
----------------
|
||||
|
||||
To lint an entire project we will need the names of all the modules
|
||||
in the project. Visual Studio keeps these names (as well as some
|
||||
appropriate options such as define options (-d...) and include options
|
||||
(-i...) in a file named NAME.vcproj in the current project directory.
|
||||
NAME is the name of the project and is identified by the macro
|
||||
$(TargetName). PC-lint can read the .vcproj file and generate the
|
||||
appropriate .lnt file. We recommend creating a tool for this purpose.
|
||||
For this tool follow the steps 1-4 doing exactly the same thing as
|
||||
above except in step 3, the information entered should be:
|
||||
|
||||
Title: PC-lint (Project Creation)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments: -v -os("$(TargetName).lnt") "$(ProjectFileName)"
|
||||
Init. Dir.: $(ProjectDir)
|
||||
|
||||
__Use Output Window __Prompt for arguments x_Close on exit
|
||||
|
||||
You will need to have an active project before this will work.
|
||||
If you don't already have one you can obtain an active project
|
||||
from the Solutions Explorer. You then click the newly added
|
||||
"PC-lint (Project Creation)" tool on the tools menu to create
|
||||
NAME.lnt.
|
||||
|
||||
The file created is an ASCII file and we recommend that you open it
|
||||
within the IDE and examine it for any obvious flaws. This is your
|
||||
chance to make any necessary modifications to the file as the process
|
||||
of conversion may be less than perfect.
|
||||
|
||||
Project Check
|
||||
-------------
|
||||
|
||||
Interestingly, by opening up the NAME.lnt file created above and
|
||||
running the Simple Check described earlier you have the equivalent
|
||||
of a full project check. However, we prefer to create a special
|
||||
Project Check tool.
|
||||
|
||||
Now that we have a project file we can create a new tool called
|
||||
"PC-lint (project check)". For this tool again follow steps 1-4 doing
|
||||
exactly the same thing as above except in step 3, the information
|
||||
entered should be:
|
||||
|
||||
Title: PC-lint (Project Check)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments: -i"c:\lint" std.lnt env-vc10.lnt "$(TargetName).lnt"
|
||||
Init. Dir.: $(ProjectDir)
|
||||
|
||||
X_Use Output Window __Prompt for arguments __Close on exit
|
||||
|
||||
Unit Check
|
||||
----------
|
||||
|
||||
You can almost do a unit check on any single module by using the
|
||||
Simple Check scheme suggested above. The only problems are that you
|
||||
will need a -u option and you will not have the benefit of any -d or
|
||||
-i options that have been placed into NAME.lnt created in the Project
|
||||
Creation step. For this reason we suggest the following tool for
|
||||
doing a unit check of any module that is part of a project and for
|
||||
which a .lnt project file has been generated.
|
||||
|
||||
Title: PC-lint (Unit Check)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments:
|
||||
-i"c:\lint" std.lnt env-vc10.lnt --u "$(TargetName).lnt" "$(ItemPath)"
|
||||
|
||||
Init. Dir.: $(ProjectDir)
|
||||
|
||||
X_Use Output Window __Prompt for arguments __Close on exit
|
||||
|
||||
Note that $(ItemPath) will provide a complete path name and in the
|
||||
absence of a project.lnt file it would cause full path names to
|
||||
appear in messages. But a side effect of using the project file
|
||||
with the --u option means that we adopt the shorter names used
|
||||
in the project file.
|
||||
|
||||
Suppressing Messages
|
||||
----------- --------
|
||||
|
||||
Suppressing messages is normally done by adding message suppression
|
||||
options to a file. For example, -e550 will suppress message 550.
|
||||
There are numerous other options to suppress messages.
|
||||
|
||||
As the documentation indicates, the file
|
||||
|
||||
c:\lint\options.lnt
|
||||
|
||||
(where c:\lint\ is the Configuration Directory) is the presumed
|
||||
container of your overall suppression policy. (Note: options.lnt is
|
||||
referenced by std.lnt). Add a message suppression here and you will
|
||||
affect all linting employing that configuration.
|
||||
|
||||
To suppress messages for a particular project (or for all projects
|
||||
within a given project directory) you may do the following:
|
||||
Create a file std.lnt that is contained in the project directory.
|
||||
Make it refer back to the std.lnt in the Configuration Directory.
|
||||
Then add additional message suppression options or indeed any options
|
||||
you want. For example it might contain:
|
||||
|
||||
c:\lint\std.lnt // reference to original std.lnt
|
||||
-e550 // project-specific option
|
||||
|
||||
In this way suppression is limited to a particular project.
|
||||
|
||||
|
||||
Tool Bar
|
||||
--------
|
||||
|
||||
You also have the option of creating a PC-lint toolbar within your
|
||||
Visual C++ IDE. First, create one or more tools as described above.
|
||||
You will need to know the number(s) of the tool(s) you want to place
|
||||
on the tool bar. This can only be done by the painful and laborious
|
||||
task of counting. Using the list provided by "Tools"/"External
|
||||
Tools", jot down the numbers (starting with 1 at the top) of all the
|
||||
tools to be added to the tool bar. We recommend placing all the
|
||||
PC-lint tools on a single tool bar. Then select Customize from the
|
||||
Tools menu. Select the Toolbars tab and click the New... button.
|
||||
Give the Toolbar a name (E.g., PC-lint) in the dialog box provided
|
||||
and click "OK". Confirm that the new toolbar is now floating on
|
||||
the desktop and that a check has been placed in the check box next
|
||||
to the new toolbar name. Then click on the Commands tab and
|
||||
select the "Toolbar:" radio button. Open the drop down list and
|
||||
select "PC-Lint" from the choices. Click the "Add Command..."
|
||||
button to reveal the "Add Command" window. In the "Categories:"
|
||||
box scroll down to and select the "Tools" item. In the
|
||||
"Commands:" box scroll down to and select the appropriate
|
||||
"External Command" numbered item that corresponds to the desired
|
||||
PC-Lint command, then click the OK button to add the selected item
|
||||
to the PC-Lint toolbar. Repeat the "Add Command..." process for
|
||||
each desired PC-Lint command the you wish to place on the PC-Lint
|
||||
toolbar.
|
||||
|
||||
If you want to add a button image to the toolbar, you can choose one
|
||||
via the Modify Selection button. Click Close and you now have your
|
||||
own PC-lint for C/C++ button. (Note: If you change the location of
|
||||
the PC-lint menu item on the Tools menu, you will change the subscript
|
||||
and you will need to change the button(s) on the toolbar.)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
-"format=%(%F(%l):%) error %n: (%t -- %m)" // Messages will contain
|
||||
// file information (%F), the line number (%l), the
|
||||
// message number (%n), message type (%t) and message text (%m).
|
||||
|
||||
-hF2 // Make sure we ALWAYS provide file information ('F') and use 2
|
||||
// lines (one for the source line in error and one for the
|
||||
// message).
|
||||
|
||||
-width(0) // don't break messages at any particular width
|
||||
-t4 // Presume that tabs are every 4 stops
|
||||
//+e900 // issue a message at termination.
|
|
@ -0,0 +1,17 @@
|
|||
/* Date Stamp */ -d"_lint_lib_ole_lnt=lib-ole.lnt modified 23-Mar-2004"
|
||||
/* To document usage use: -message( "Using " _lint_lib_ole_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// BSTR functions (part of OLE Automation)
|
||||
|
||||
-sem( SysAllocString, @p == malloc(1p) || @p == 0, 1p )
|
||||
-sem( SysAllocStringByteLen, @P == malloc(2n+1) || @p == 0 )
|
||||
-sem( SysAllocStringLen, @p == malloc(2n+1) || @p == 0 )
|
||||
-sem( SysStringLen, 1p ? @n == 1p - 1 : @n == 0 )
|
||||
-function( free, SysFreeString )
|
|
@ -0,0 +1,56 @@
|
|||
/* Date Stamp */ -d"_lint_lib_w32_lnt=lib-w32.lnt modified 2-Mar-1999"
|
||||
/* To document usage use: -message( "Using " _lint_lib_w32_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// lib-w32.lnt
|
||||
// PC-lint Library Options File for 32-bit mode windows.h
|
||||
|
||||
-d__FLAT__
|
||||
-d_WIN32
|
||||
-si4
|
||||
-sp4
|
||||
-esym(14,pLocalHeap) // variable defined in windows.h
|
||||
-e740 // remove 'suspicious cast' messages because these must be
|
||||
// routinely done within Windows.
|
||||
-elib(46) // windows.h uses a BYTE as base of bit field.
|
||||
-e793 // windows breaks ANSI limits
|
||||
|
||||
// the following functions have their return value typically ignored.
|
||||
// add or subtract from this list as desired.
|
||||
-esym(534,RegisterClass,ShowWindow,TranslateMessage,DispatchMessage)
|
||||
-esym(534,DrawText,GetTextMetrics,ReleaseDC,TextOut,SetTextAlign)
|
||||
-esym(534,SetScrollPos,SelectObject,SetBkMode,SendMessage,MessageBox)
|
||||
-esym(534,MessageBoxA,MessageBoxW,PostMessageA,PostMessageW)
|
||||
-esym(534,PatBlt,DeleteDC,SetCapture,SetCursor,StretchBlt)
|
||||
-esym(534,Rectangle,MoveTo,LineTo,ShowCursor,MoveWindow,SetWindowWord)
|
||||
-esym(534,SetPixel,FillRect,DeleteObject,KillTimer,GetProfileString)
|
||||
-esym(534,SetWindowLong,SetFocus,SetBkColor,SetTextColor,SetBrushOrg)
|
||||
-esym(534,UnrealizeObject,_lclose,Polygon,FrameRect,LoadString)
|
||||
-esym(534,GetInstanceData,GlobalUnlock,FreeResource,LoadString)
|
||||
-esym(534,DrawIcon,AppendMenu,GetObject,CheckMenuItem,SetClassWord)
|
||||
-esym(534,EnableMenuItem,SetMenu,DestroyMenu,TrackPopupMenu)
|
||||
-esym(534,AnsiUpper,Arc,BeginPaint,BitBlt,ChangeClipboardChain,Chord)
|
||||
-esym(534,CloseClipboard,CombineRgn,DdeClientTransaction,DdeDisconnect)
|
||||
-esym(534,DdeFreeStringHandle,DdeGetData,DdeNameService,DdePostAdvise)
|
||||
-esym(534,DdeQueryString,DdeUninitialize,DeleteMenu,DeleteMetaFile)
|
||||
-esym(534,DestroyWindow,DialogBox,DPtoLP,Ellipse,EmptyClipboard,EnableWindow)
|
||||
-esym(534,EnumChildWindows,EnumWindows,Escape,GetClassName,GetDlgItemText)
|
||||
-esym(534,GetFileTitle,GetMenuString,GetStrings,GetSystemMenu,GetTextFace)
|
||||
-esym(534,GetWindowText,GlobalDeleteAtom,GlobalFree,GlobalGetAtomName)
|
||||
-esym(534,LocalFree,LocalUnlock,LockResource,lstrcpy,OpenClipboard)
|
||||
-esym(534,Pie,PlayMetaFile,PopFindNextText,PostDataMessage,PostMessage)
|
||||
-esym(534,RestoreDC,SaveDC,SelectClipRgn,SendDlgItemMessage,SetClipboardData)
|
||||
-esym(534,SetDIBitsToDevice,SetMapMode,SetMapperFlags,SetROP2,SetStretchBltMode)
|
||||
-esym(534,SetTextJustification,SetTimer,SetViewportExt,SetViewportOrg)
|
||||
-esym(534,SetWindowExt,SetWindowOrg,StretchDIBits,WinExec)
|
||||
|
||||
// Ignored parameters
|
||||
-esym(715,lpszCmdParam,lpszCmdLine)
|
||||
|
||||
-emacro(648,PSN_*) // ignore unsigned overflow (0-200U)
|
|
@ -0,0 +1,85 @@
|
|||
# This file contains functions and configurations for generating PC-Lint build
|
||||
# targets for your CMake projects.
|
||||
|
||||
set(PC_LINT_EXECUTABLE "C:/Lint/lint-nt.exe" CACHE STRING "full path to the pc-lint executable. NOT the generated lin.bat")
|
||||
set(PC_LINT_CONFIG_DIR "${PROJECT_SOURCE_DIR}/lint/msvc" CACHE STRING "full path to the directory containing pc-lint configuration files")
|
||||
set(PC_LINT_USER_FLAGS "-b" CACHE STRING "additional pc-lint command line options -- some flags of pc-lint cannot be set in option files (most notably -b)")
|
||||
|
||||
# a phony target which causes all available *_LINT targets to be executed
|
||||
add_custom_target(ALL_LINT)
|
||||
|
||||
# add_pc_lint(target source1 [source2 ...])
|
||||
#
|
||||
# Takes a list of source files and generates a build target which can be used
|
||||
# for linting all files
|
||||
#
|
||||
# The generated lint commands assume that a top-level config file named
|
||||
# 'std.lnt' resides in the configuration directory 'PC_LINT_CONFIG_DIR'. This
|
||||
# config file must include all other config files. This is standard lint
|
||||
# behaviour.
|
||||
#
|
||||
# Parameters:
|
||||
# - target: the name of the target to which the sources belong. You will get a
|
||||
# new build target named ${target}_LINT
|
||||
# - source1 ... : a list of source files to be linted. Just pass the same list
|
||||
# as you passed for add_executable or add_library. Everything except
|
||||
# C and CPP files (*.c, *.cpp, *.cxx) will be filtered out.
|
||||
#
|
||||
# Example:
|
||||
# If you have a CMakeLists.txt which generates an executable like this:
|
||||
#
|
||||
# set(MAIN_SOURCES main.c foo.c bar.c)
|
||||
# add_executable(main ${MAIN_SOURCES})
|
||||
#
|
||||
# include this file
|
||||
#
|
||||
# include(/path/to/pc_lint.cmake)
|
||||
#
|
||||
# and add a line to generate the main_LINT target
|
||||
#
|
||||
# if(COMMAND add_pc_lint)
|
||||
# add_pc_lint(main ${MAIN_SOURCES})
|
||||
# endif(COMMAND add_pc_lint)
|
||||
#
|
||||
function(add_pc_lint target)
|
||||
get_directory_property(lint_include_directories INCLUDE_DIRECTORIES)
|
||||
get_directory_property(lint_defines COMPILE_DEFINITIONS)
|
||||
|
||||
# let's get those elephants across the alps
|
||||
# prepend each include directory with "-i"; also quotes the directory
|
||||
set(lint_include_directories_transformed)
|
||||
foreach(include_dir ${lint_include_directories})
|
||||
list(APPEND lint_include_directories_transformed -i"${include_dir}")
|
||||
endforeach(include_dir)
|
||||
|
||||
# prepend each definition with "-d"
|
||||
set(lint_defines_transformed)
|
||||
foreach(definition ${lint_defines})
|
||||
list(APPEND lint_defines_transformed -d${definition})
|
||||
endforeach(definition)
|
||||
|
||||
# list of all commands, one for each given source file
|
||||
set(pc_lint_commands)
|
||||
|
||||
foreach(sourcefile ${ARGN})
|
||||
# only include c and cpp files
|
||||
if( sourcefile MATCHES \\.c$|\\.cxx$|\\.cpp$ )
|
||||
# make filename absolute
|
||||
get_filename_component(sourcefile_abs ${sourcefile} ABSOLUTE)
|
||||
# create command line for linting one source file and add it to the list of commands
|
||||
list(APPEND pc_lint_commands
|
||||
COMMAND ${PC_LINT_EXECUTABLE}
|
||||
-i"${PC_LINT_CONFIG_DIR}" std.lnt
|
||||
"-u" ${PC_LINT_USER_FLAGS}
|
||||
${lint_include_directories_transformed}
|
||||
${lint_defines_transformed}
|
||||
${sourcefile_abs})
|
||||
endif()
|
||||
endforeach(sourcefile)
|
||||
|
||||
# add a custom target consisting of all the commands generated above
|
||||
add_custom_target(${target}_LINT ${pc_lint_commands} VERBATIM)
|
||||
# make the ALL_LINT target depend on each and every *_LINT target
|
||||
add_dependencies(ALL_LINT ${target}_LINT)
|
||||
|
||||
endfunction(add_pc_lint)
|
|
@ -0,0 +1,4 @@
|
|||
co-msc100.lnt
|
||||
env-vc10.lnt
|
||||
lib-w32.lnt
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
\mainpage BootCommander - Command Line Firmware Update Tool
|
||||
\details
|
||||
\tableofcontents
|
||||
\section into Introduction
|
||||
BootCommander is a command line program for performing a firmware update on a connected
|
||||
microcontroller target that runs the OpenBLT bootloader. It is written in the C
|
||||
programming language (C99) and is cross-platform. It has been successfully tested on a
|
||||
Windows PC, Linux PC and even embedded Linux systems such as a Raspberry Pi and a Beagle
|
||||
Board.
|
||||
|
||||
BootCommander is built on top of the OpenBLT Host Library (LibOpenBLT), which embeds all
|
||||
functionality needed to communicate with the OpenBLT bootloader on the microcontroller
|
||||
target.
|
||||
|
||||
\image html bootcommander_architecture.png
|
||||
\image latex bootcommander_architecture.png
|
||||
|
||||
This program is specifically developed for those that prefer a command line program over
|
||||
a program with a graphical user interface, such as MicroBoot. Additionally, it can
|
||||
serve as a reference on how to use LibOpenBLT.
|
||||
|
||||
Refer to the OpenBLT website for additional information regarding the usage of the
|
||||
BootCommander program, including a description of the available command line parameters
|
||||
and step-by-step instructions on how to build the BootCommander program from sources:
|
||||
https://www.feaser.com/openblt/doku.php?id=manual:bootcommander.
|
||||
|
||||
\verbatim
|
||||
----------------------------------------------------------------------------------------
|
||||
C O P Y R I G H T
|
||||
----------------------------------------------------------------------------------------
|
||||
Copyright (c) 2017 Feaser. All rights reserved.
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
L I C E N S E
|
||||
----------------------------------------------------------------------------------------
|
||||
This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
----------------------------------------------------------------------------------------
|
||||
\endverbatim
|
||||
|
||||
*/
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
#****************************************************************************************
|
||||
# \file CMakeLists.txt
|
||||
# \brief CMake descriptor file for the OpenBLT host library.
|
||||
# \internal
|
||||
#----------------------------------------------------------------------------------------
|
||||
# C O P Y R I G H T
|
||||
#----------------------------------------------------------------------------------------
|
||||
# Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
#
|
||||
#----------------------------------------------------------------------------------------
|
||||
# L I C E N S E
|
||||
#----------------------------------------------------------------------------------------
|
||||
# This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
# PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
# should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
#
|
||||
# \endinternal
|
||||
#****************************************************************************************
|
||||
# Specify the version being used aswell as the language
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
|
||||
#****************************************************************************************
|
||||
# Project configuration
|
||||
#****************************************************************************************
|
||||
# Specify the project name
|
||||
project(LibOpenBLT)
|
||||
|
||||
# Build debug version by default
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
|
||||
|
||||
#****************************************************************************************
|
||||
# Options
|
||||
#****************************************************************************************
|
||||
# Add option with default value to enable the generation and building of the static
|
||||
# library. It can be overridden on the command line when CMake is called using the
|
||||
# following parameter: -DBUILD_STATIC=OFF
|
||||
option(BUILD_STATIC "Configurable to enable/disable building of the static library" ON)
|
||||
|
||||
# Add option with default value to enable the generation and building of the shared
|
||||
# library. It can be overridden on the command line when CMake is called using the
|
||||
# following parameter: -DBUILD_SHARED=OFF
|
||||
option(BUILD_SHARED "Configurable to enable/disable building of the shared library" ON)
|
||||
|
||||
# Add option with default value to disable the generation of the PC-lint target. It can
|
||||
# be overridden on the command line when CMake is called using the following parameter:
|
||||
# -DLINT_ENABLED=ON
|
||||
option(LINT_ENABLED "Configurable to enable/disable the PC-lint target" OFF)
|
||||
|
||||
|
||||
#****************************************************************************************
|
||||
# Directories
|
||||
#****************************************************************************************
|
||||
# Set the port directory, which is platform specific
|
||||
if(WIN32)
|
||||
set(PROJECT_PORT_DIR ${PROJECT_SOURCE_DIR}/port/windows)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_WIN32 -D_CRT_SECURE_NO_WARNINGS")
|
||||
elseif(UNIX)
|
||||
set(PROJECT_PORT_DIR ${PROJECT_SOURCE_DIR}/port/linux)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_LINUX")
|
||||
endif(WIN32)
|
||||
|
||||
# Set the output directory
|
||||
set (PROJECT_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../../..)
|
||||
|
||||
# Set the output directory for the generic no-config case (e.g. with mingw)
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
# Set the output directory for multi-config builds (e.g. msvc)
|
||||
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
|
||||
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_OUTPUT_DIRECTORY} )
|
||||
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
|
||||
|
||||
|
||||
#***************************************************************************************
|
||||
# Includes
|
||||
#****************************************************************************************
|
||||
# Set include directories
|
||||
include_directories("${PROJECT_SOURCE_DIR}" "${PROJECT_PORT_DIR}")
|
||||
|
||||
|
||||
#***************************************************************************************
|
||||
# Files
|
||||
#****************************************************************************************
|
||||
# Get header files from the root directory and the port directory.
|
||||
file(GLOB INCS_ROOT "*.h")
|
||||
file(GLOB INCS_PORT "${PROJECT_PORT_DIR}/*.h")
|
||||
set(INCS ${INCS_ROOT} ${INCS_PORT})
|
||||
|
||||
# Add sources
|
||||
set(
|
||||
LIB_SRCS
|
||||
openblt.c
|
||||
session.c
|
||||
xcploader.c
|
||||
xcptpuart.c
|
||||
firmware.c
|
||||
srecparser.c
|
||||
util.c
|
||||
${PROJECT_PORT_DIR}/timeutil.c
|
||||
${PROJECT_PORT_DIR}/serialport.c
|
||||
${INCS}
|
||||
)
|
||||
|
||||
|
||||
#***************************************************************************************
|
||||
# Targets
|
||||
#****************************************************************************************
|
||||
# Only generate the static library taget if the option is enabled. Use
|
||||
# "make openblt_static" to individually build the static library.
|
||||
if(BUILD_STATIC)
|
||||
add_library(openblt_static STATIC ${LIB_SRCS})
|
||||
SET_TARGET_PROPERTIES(openblt_static PROPERTIES OUTPUT_NAME openblt CLEAN_DIRECT_OUTPUT 1)
|
||||
endif(BUILD_STATIC)
|
||||
|
||||
# Only generate the shared library taget if the option is enabled. Use
|
||||
# "make openblt_shared" to build individually shared library.
|
||||
if(BUILD_SHARED)
|
||||
add_library(openblt_shared SHARED ${LIB_SRCS})
|
||||
if(CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
# Microsoft Visual Studio does not add "lib" to the name of the DLL, whereas GCC
|
||||
# (including MinGW) does. Correct this here.
|
||||
SET_TARGET_PROPERTIES(openblt_shared PROPERTIES OUTPUT_NAME libopenblt CLEAN_DIRECT_OUTPUT 1)
|
||||
else()
|
||||
SET_TARGET_PROPERTIES(openblt_shared PROPERTIES OUTPUT_NAME openblt CLEAN_DIRECT_OUTPUT 1)
|
||||
endif()
|
||||
endif(BUILD_SHARED)
|
||||
|
||||
# Only generate the PC-lint taget if the option is enabled. Use "make openblt_LINT" to
|
||||
# lint the project sources
|
||||
if(LINT_ENABLED)
|
||||
# Include PC-lint configuration file for the correct compiler. Currently GNU GCC and
|
||||
# Microsoft Visual Studio are supported.
|
||||
if(CMAKE_C_COMPILER_ID MATCHES GNU)
|
||||
include(${PROJECT_SOURCE_DIR}/lint/gnu/pc_lint.cmake)
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
include(${PROJECT_SOURCE_DIR}/lint/msvc/pc_lint.cmake)
|
||||
endif()
|
||||
|
||||
# Generate the PC-lint target.
|
||||
if(COMMAND add_pc_lint)
|
||||
add_pc_lint(openblt ${LIB_SRCS})
|
||||
endif(COMMAND add_pc_lint)
|
||||
endif(LINT_ENABLED)
|
||||
|
||||
|
||||
#*********************************** end of CMakeLists.txt ******************************
|
|
@ -0,0 +1,874 @@
|
|||
/************************************************************************************//**
|
||||
* \file firmware.c
|
||||
* \brief Firmware data module source file.
|
||||
* \ingroup Firmware
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <stdlib.h> /* for standard library */
|
||||
#include <string.h> /* for string library */
|
||||
#include "firmware.h" /* Firmware data module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Pointer to the firmware parser that is linked. */
|
||||
static tFirmwareParser const * parserPtr;
|
||||
|
||||
/** \brief Linked list with firmware segments. */
|
||||
static tFirmwareSegment * segmentList;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
static void FirmwareCreateSegment(uint32_t address, uint32_t len, uint8_t const * data);
|
||||
static void FirmwareDeleteSegment(tFirmwareSegment const * segment);
|
||||
static void FirmwareTrimSegment(tFirmwareSegment const * segment, uint32_t address,
|
||||
uint32_t len);
|
||||
static void FirmwareSortSegments(void);
|
||||
static void FirmwareMergeSegments(void);
|
||||
static uint32_t FirmwareGetFirstAddress(void);
|
||||
static uint32_t FirmwareGetLastAddress(void);
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the module.
|
||||
** \param parser The firmware file parser to link. It is okay to specify NULL if no
|
||||
** file parser is needed.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void FirmwareInit(tFirmwareParser const * parser)
|
||||
{
|
||||
/* Link the firmware parser. */
|
||||
parserPtr = parser;
|
||||
/* Start with an empty segment list. */
|
||||
segmentList = NULL;
|
||||
} /*** end of FirmwareInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void FirmwareTerminate(void)
|
||||
{
|
||||
/* Clear all data and segments from the linked list. */
|
||||
FirmwareClearData();
|
||||
/* Unlink the firmware parser. */
|
||||
parserPtr = NULL;
|
||||
} /*** end of FirmwareTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Uses the linked parser to load the firmware data from the specified file
|
||||
** into the linked list of segments.
|
||||
** \param firmwareFile Filename of the firmware file to load.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool FirmwareLoadFromFile(char const * firmwareFile)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(firmwareFile != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (firmwareFile != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Check if a parser is linked. */
|
||||
if (parserPtr != NULL)
|
||||
{
|
||||
/* Check if a LoadFromFile method is linked. */
|
||||
if (parserPtr->LoadFromFile != NULL)
|
||||
{
|
||||
/* Request the parser to perform the load operation. */
|
||||
result = parserPtr->LoadFromFile(firmwareFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of FirmwareLoadFromFile ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Uses the linked parser to save the dat stored in the segments of the linked
|
||||
** list to the specified file.
|
||||
** \param firmwareFile Filename of the firmware file to write to.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool FirmwareSaveToFile(char const * firmwareFile)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(firmwareFile != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (firmwareFile != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Check if a parser is linked. */
|
||||
if (parserPtr != NULL)
|
||||
{
|
||||
/* Check if a SaveToFile method is linked. */
|
||||
if (parserPtr->SaveToFile != NULL)
|
||||
{
|
||||
/* Request the parser to perform the save operation. */
|
||||
result = parserPtr->SaveToFile(firmwareFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of FirmwareSaveToFile ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains the total number of segments in the linked list with firmware data.
|
||||
** \return Total number of segments.
|
||||
**
|
||||
****************************************************************************************/
|
||||
uint32_t FirmwareGetSegmentCount(void)
|
||||
{
|
||||
tFirmwareSegment * currentSegment;
|
||||
uint32_t segmentCount = 0;
|
||||
|
||||
/* Iterate over all segments to determine the total count. */
|
||||
if (segmentList != NULL)
|
||||
{
|
||||
currentSegment = segmentList;
|
||||
do
|
||||
{
|
||||
segmentCount++;
|
||||
currentSegment = currentSegment->next;
|
||||
}
|
||||
while (currentSegment != NULL);
|
||||
}
|
||||
/* Give segment count back to the caller. */
|
||||
return segmentCount;
|
||||
} /*** end of FirmwareGetSegmentCount ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains the segment as the specified index from the linked list with
|
||||
** firmware data.
|
||||
** \param segmentIdx The segment index. It should be a value greater or equal to zero
|
||||
** and smaller than the value returned by \ref FirmwareGetSegmentCount.
|
||||
** \return The segment if successful, NULL otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
tFirmwareSegment * FirmwareGetSegment(uint32_t segmentIdx)
|
||||
{
|
||||
tFirmwareSegment * currentSegment = NULL;
|
||||
uint32_t currentIdx;
|
||||
|
||||
/* Validate parameters. */
|
||||
assert(segmentIdx < FirmwareGetSegmentCount());
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (segmentIdx < FirmwareGetSegmentCount())
|
||||
{
|
||||
/* Iterate over the segments until the specified index is found. */
|
||||
if (segmentList != NULL)
|
||||
{
|
||||
currentSegment = segmentList;
|
||||
for (currentIdx = 0; currentIdx < segmentIdx; currentIdx++)
|
||||
{
|
||||
/* Move on to the next segment. */
|
||||
currentSegment = currentSegment->next;
|
||||
/* Make sure the segment is valid. */
|
||||
assert(currentSegment != NULL);
|
||||
if (currentSegment == NULL) /*lint !e774 */
|
||||
{
|
||||
/* The specified index tries to index a non-existing segment. Abort. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the requested segment back to the caller, if found. */
|
||||
return currentSegment;
|
||||
} /*** end of FirmwareGetSegment ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Adds data to the segments that are currently present in the firmware data
|
||||
** module. If the data overlaps with already existing data, the existing data
|
||||
** gets overwritten. The size of a segment is automatically adjusted or a new
|
||||
** segment gets created, if necessary.
|
||||
** \param address Base address of the firmware data.
|
||||
** \param len Number of bytes to add.
|
||||
** \param data Pointer to array with data bytes that should be added.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool FirmwareAddData(uint32_t address, uint32_t len, uint8_t const * data)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(len > 0);
|
||||
assert(data != NULL);
|
||||
|
||||
(void)address;
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ( (len > 0) && (data != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* The to be added data could span several existing segments, eithe partially or
|
||||
* completely. If is therefore faster to first remove the same range, and then
|
||||
* add the data as one new segment.
|
||||
*/
|
||||
if (FirmwareRemoveData(address, len))
|
||||
{
|
||||
/* Next add the new data as a new segment. */
|
||||
FirmwareCreateSegment(address, len, data);
|
||||
/* Merge the segments after adding a new one. Note that this automatically sorts
|
||||
* the segments as well.
|
||||
*/
|
||||
FirmwareMergeSegments();
|
||||
/* Data successfully added. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of FirmwareAddData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Removes data from the segments that are currently present in the firmware
|
||||
** data module. The size of a segment is automatically adjusted or removed, if
|
||||
** necessary. Note that it is safe to assume in this function that the
|
||||
** segments are already ordered in the linked list by ascending base memory
|
||||
** address.
|
||||
** \param address Base address of the firmware data.
|
||||
** \param len Number of bytes to remove.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool FirmwareRemoveData(uint32_t address, uint32_t len)
|
||||
{
|
||||
bool result = false;
|
||||
tFirmwareSegment * startSegment = NULL;
|
||||
tFirmwareSegment * endSegment = NULL;
|
||||
uint32_t startSegmentIdx;
|
||||
uint32_t endSegmentIdx;
|
||||
tFirmwareSegment * currentSegment;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (len > 0)
|
||||
{
|
||||
/* In case there are no segments yet in the list, there is nothing extra to do. */
|
||||
if (segmentList == NULL)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
/* At least one segment in the list. Check if the to be erased data falls outside the
|
||||
* range of the segments that are currently in the linked list. In this case there
|
||||
* is nothing extra to do.
|
||||
*/
|
||||
else if ( ((address + len - 1u) < FirmwareGetFirstAddress()) ||
|
||||
(address > FirmwareGetLastAddress()) )
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
/* At least one segment in the list and the to be erased data overlaps one or more
|
||||
* segments.
|
||||
*/
|
||||
else
|
||||
{
|
||||
/* Find the segment with the lowest index that contains data to remove. */
|
||||
currentSegment = segmentList;
|
||||
startSegmentIdx = 0;
|
||||
do
|
||||
{
|
||||
/* Is there to be removed data in this segment? */
|
||||
if (address < (currentSegment->base + currentSegment->length))
|
||||
{
|
||||
/* Start segment found. Store it and stop looping. */
|
||||
startSegment = currentSegment;
|
||||
break;
|
||||
}
|
||||
/* Continue with the next segment. */
|
||||
currentSegment = currentSegment->next;
|
||||
startSegmentIdx++;
|
||||
}
|
||||
while (currentSegment != NULL);
|
||||
|
||||
/* Find the segment with the highest index that contains data to remove. */
|
||||
currentSegment = FirmwareGetSegment(FirmwareGetSegmentCount() - 1u);
|
||||
endSegmentIdx = FirmwareGetSegmentCount() - 1u;
|
||||
do
|
||||
{
|
||||
/* Is there to be removed data in this segment? */
|
||||
if (currentSegment->base < (address + len))
|
||||
{
|
||||
/* End segment found. Store it and stop looping. */
|
||||
endSegment = currentSegment;
|
||||
break;
|
||||
}
|
||||
/* Continue with the previous segment. */
|
||||
currentSegment = currentSegment->prev;
|
||||
endSegmentIdx--;
|
||||
}
|
||||
while (currentSegment != NULL);
|
||||
|
||||
/* Sanity check. The start- and endSegments must be valid now. */
|
||||
assert((startSegment != NULL) && (endSegment != NULL));
|
||||
/* Only continue if segment pointers are valid. */
|
||||
if ((startSegment != NULL) && (endSegment != NULL)) /*lint !e774 */
|
||||
{
|
||||
/* Check if the endSegmentIdx is smaller than the startSegmentIdx. This indicates
|
||||
* that the to be erased data falls in a gap between 2 segments and that is
|
||||
* nothing to remove.
|
||||
*/
|
||||
if (endSegmentIdx < startSegmentIdx)
|
||||
{
|
||||
/* Nothing to remove, so we are all done. */
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove all segments in between the start- and endSegments, if any */
|
||||
if (startSegment != endSegment)
|
||||
{
|
||||
/* Delete the segments until the endSegment is reached. */
|
||||
while (startSegment->next != endSegment)
|
||||
{
|
||||
/* Note that this automatically updates the next-member to the segment after
|
||||
* the one that got deleted.
|
||||
*/
|
||||
FirmwareDeleteSegment(startSegment->next);
|
||||
}
|
||||
}
|
||||
/* Segments between the start- and endSegment are now removed. Now trim the
|
||||
* start- and endSegments.
|
||||
*/
|
||||
FirmwareTrimSegment(startSegment, address, len);
|
||||
/* Only trim endSegment if it is different from the startSegment. */
|
||||
if (startSegment != endSegment)
|
||||
{
|
||||
FirmwareTrimSegment(endSegment, address, len);
|
||||
}
|
||||
/* Resort the segments because new segments might have been added during
|
||||
* the trim operation.
|
||||
*/
|
||||
FirmwareSortSegments();
|
||||
/* Segment removal completed successfully. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of FirmwareRemoveData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Clears all data and segments that are currently present in the linked list.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void FirmwareClearData(void)
|
||||
{
|
||||
tFirmwareSegment * currentSegment;
|
||||
tFirmwareSegment * segmentToFree;
|
||||
|
||||
/* Free al the segments in the segment list. */
|
||||
if (segmentList != NULL)
|
||||
{
|
||||
currentSegment = segmentList;
|
||||
do
|
||||
{
|
||||
/* Store pointer to the segment that should be released for later usage. */
|
||||
segmentToFree = currentSegment;
|
||||
/* Move to the next segment before freeing it. */
|
||||
currentSegment = currentSegment->next;
|
||||
/* Sanity check. */
|
||||
assert(segmentToFree != NULL);
|
||||
/* Only access the segment if it is not NULL. */
|
||||
if (segmentToFree != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Free the segment data. */
|
||||
if (segmentToFree->data != NULL)
|
||||
{
|
||||
free(segmentToFree->data);
|
||||
}
|
||||
/* Free the segment. */
|
||||
free(segmentToFree);
|
||||
}
|
||||
}
|
||||
while (currentSegment != NULL);
|
||||
/* Set the segment list to empty. */
|
||||
segmentList = NULL;
|
||||
}
|
||||
} /*** end of FirmwareClearData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Creates and adds a new segment to the linked list. It allocates memory for
|
||||
** the segment data and copies the data to it.
|
||||
** \param address Base address of the firmware data.
|
||||
** \param len Number of bytes to add to the new segment.
|
||||
** \param data Pointer to the byte array with data for the segment.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void FirmwareCreateSegment(uint32_t address, uint32_t len, uint8_t const * data)
|
||||
{
|
||||
/*lint -esym(593, newSegment) newSegment pointer is freed when the segment is removed
|
||||
* from the linked list.
|
||||
*/
|
||||
tFirmwareSegment * newSegment;
|
||||
tFirmwareSegment * currentSegment;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(len > 0);
|
||||
assert(data != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ( (len > 0) && (data != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Allocate memory for the new segment. */
|
||||
newSegment = malloc(sizeof(tFirmwareSegment));
|
||||
/* Verify allocation result. */
|
||||
assert(newSegment != NULL);
|
||||
/* Only continue if allocation was successful. */
|
||||
if (newSegment != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Allocate memory for the segment data. */
|
||||
newSegment->data = malloc(len);
|
||||
/* Verify allocation result. */
|
||||
assert(newSegment->data != NULL);
|
||||
/* Only continue if allocation was successful. */
|
||||
if (newSegment->data != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Copy the data to the segment. */
|
||||
memcpy(newSegment->data, data, len);
|
||||
/* Set other segment fields. */
|
||||
newSegment->base = address;
|
||||
newSegment->length = len;
|
||||
newSegment->next = NULL;
|
||||
/* Add the new segment as the first segment if the linked list is empty. */
|
||||
if (segmentList == NULL)
|
||||
{
|
||||
newSegment->prev = NULL;
|
||||
segmentList = newSegment;
|
||||
}
|
||||
/* Add the segment to the end of the list. */
|
||||
else
|
||||
{
|
||||
/* Find the last entry in the list. */
|
||||
currentSegment = segmentList;
|
||||
while (currentSegment->next != NULL)
|
||||
{
|
||||
currentSegment = currentSegment->next;
|
||||
}
|
||||
/* Add the new segment. */
|
||||
newSegment->prev = currentSegment;
|
||||
currentSegment->next = newSegment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /*** end of FirmwareCreateSegment ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Deletes the specified segment from the linked list and handles
|
||||
** the release of the segment's allocated memory.
|
||||
** \param segment Pointer to the segment.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void FirmwareDeleteSegment(tFirmwareSegment const * segment)
|
||||
{
|
||||
tFirmwareSegment * currentSegment = NULL;
|
||||
|
||||
/* Validate parameters. */
|
||||
assert(segment != NULL);
|
||||
|
||||
/* Only continue if parameters are valid and the linked list is not empty. */
|
||||
if ( (segment != NULL) && (segmentList != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Iterate over the segments in the linked list, just to verify that it is a valid
|
||||
* segment pointer.
|
||||
*/
|
||||
currentSegment = segmentList;
|
||||
do
|
||||
{
|
||||
/* Is this the segment that is requested to be deleted? */
|
||||
if (currentSegment == segment)
|
||||
{
|
||||
/* Is the segment the first one in the linked list? */
|
||||
if (currentSegment->prev == NULL)
|
||||
{
|
||||
/* Make the next segment the start of the linked list, if present. */
|
||||
if (currentSegment->next != NULL)
|
||||
{
|
||||
currentSegment->next->prev = NULL;
|
||||
segmentList = currentSegment->next;
|
||||
}
|
||||
/* The to be deleted segment was the only segment in the list. So set the
|
||||
* list to empty now.
|
||||
*/
|
||||
else
|
||||
{
|
||||
segmentList = NULL;
|
||||
}
|
||||
}
|
||||
/* Is the segment the last one in the linked list? Note that we already know that
|
||||
* it is not the first one due to the previous check. This automatically means
|
||||
* there are at least 2 segments in the list, so there is no need to check its
|
||||
* previous entry pointer for NULL.
|
||||
*/
|
||||
else if (currentSegment->next == NULL)
|
||||
{
|
||||
/* Make the previous segment the end of the linked list. */
|
||||
currentSegment->prev->next = NULL;
|
||||
}
|
||||
/* It is a segment somewhere in the middle of the list. Note that we already know
|
||||
* that it is not the first or the last segment. This means that there are at
|
||||
* least three or more segments in the list, so there is no need to check the
|
||||
* next and previous entry pointers for NULL.
|
||||
*/
|
||||
else
|
||||
{
|
||||
/* Update links of adjacent segments as to remove ourselves. */
|
||||
currentSegment->prev->next = currentSegment->next;
|
||||
currentSegment->next->prev = currentSegment->prev;
|
||||
}
|
||||
/* The segment was removed from the list. Now its allocated memory should be
|
||||
* released.
|
||||
*/
|
||||
if (currentSegment->data != NULL)
|
||||
{
|
||||
free(currentSegment->data);
|
||||
}
|
||||
free(currentSegment);
|
||||
/* No need to continue looping as we are done already. */
|
||||
break;
|
||||
}
|
||||
/* Move on to the next segment. */
|
||||
currentSegment = currentSegment->next;
|
||||
}
|
||||
while (currentSegment != NULL);
|
||||
}
|
||||
} /*** end of FirmwareDeleteSegment ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Removes the specified data range (address to address + len) from the
|
||||
** segment. If if overlaps the entire segment, the segment will be deleted.
|
||||
** Otherwise, the segment will be trimmed and, if needed, split into multiple
|
||||
** segments.
|
||||
** \param segment Pointer to the segment to trim.
|
||||
** \param address Start address of the data that should be removed.
|
||||
** \param len Total number of data bytes that should be removed.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void FirmwareTrimSegment(tFirmwareSegment const * segment, uint32_t address,
|
||||
uint32_t len)
|
||||
{
|
||||
tFirmwareSegment * currentSegment = NULL;
|
||||
bool segmentValid = false;
|
||||
uint32_t newLength1, newLength2;
|
||||
uint32_t newBase1, newBase2;
|
||||
uint8_t *newData1, *newData2;
|
||||
|
||||
/* Validate parameters. */
|
||||
assert(segment != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if parameters are valid and the linked list is not empty. */
|
||||
if ( (segment != NULL) && (len > 0) && (segmentList != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Iterate over the segments in the linked list, just to verify that it is a valid
|
||||
* segment pointer.
|
||||
*/
|
||||
currentSegment = segmentList;
|
||||
do
|
||||
{
|
||||
/* Is this the segment that is requested to be trimmed? */
|
||||
if (currentSegment == segment)
|
||||
{
|
||||
/* Set flag that the specified segment is valid. */
|
||||
segmentValid = true;
|
||||
break;
|
||||
}
|
||||
/* Move on to the next segment. */
|
||||
currentSegment = currentSegment->next;
|
||||
}
|
||||
while (currentSegment != NULL);
|
||||
|
||||
/* Only continue if the segment was successfully validated. */
|
||||
if (segmentValid)
|
||||
{
|
||||
/* Does the data range to trim cover the entire segment? */
|
||||
if ((address <= segment->base) &&
|
||||
((address + len) >= (segment->base + segment->length)))
|
||||
{
|
||||
/* Delete the entire segment. */
|
||||
FirmwareDeleteSegment(segment);
|
||||
}
|
||||
/* Does the data range cover the start of the segment, but does not go all the way
|
||||
* to the end?
|
||||
*/
|
||||
else if (address <= segment->base)
|
||||
{
|
||||
/* Create a new segment with the data that should remain in the segment. */
|
||||
newBase1 = address + len;
|
||||
newLength1 = (segment->base + segment->length) - (address + len);
|
||||
newData1 = &(segment->data[newBase1 - segment->base]);
|
||||
FirmwareCreateSegment(newBase1, newLength1, newData1);
|
||||
/* The original segment can now be deleted. */
|
||||
FirmwareDeleteSegment(segment);
|
||||
}
|
||||
/* does the data range cover the end of the segment, but does not go all the way to
|
||||
* the start?
|
||||
*/
|
||||
else if ((address + len) >= (segment->base + segment->length))
|
||||
{
|
||||
/* Create a new segment with the data that should remain in the segment. */
|
||||
newBase1 = segment->base;
|
||||
newLength1 = address - segment->base;
|
||||
newData1 = segment->data;
|
||||
FirmwareCreateSegment(newBase1, newLength1, newData1);
|
||||
/* The original segment can now be deleted. */
|
||||
FirmwareDeleteSegment(segment);
|
||||
}
|
||||
/* The data range covers a part in the middle of the segment. A split is needed. */
|
||||
else
|
||||
{
|
||||
/* Create a new segment with the data that should remain in the segment that is
|
||||
* currently before the to be removed range and create a new segment with the data
|
||||
* that should remain in the segment that is currently after the to be removed
|
||||
* range.
|
||||
*/
|
||||
newBase1 = segment->base;
|
||||
newLength1 = address - segment->base;
|
||||
newData1 = segment->data;
|
||||
newBase2 = address + len;
|
||||
newLength2 = (segment->base + segment->length) - (address + len);
|
||||
newData2 = &(segment->data[newBase2 - segment->base]);
|
||||
FirmwareCreateSegment(newBase1, newLength1, newData1);
|
||||
FirmwareCreateSegment(newBase2, newLength2, newData2);
|
||||
/* The original segment can now be deleted. */
|
||||
FirmwareDeleteSegment(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
} /*** end of FirmwareTrimSegment ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Helper function to sort the segments in the linked list in order of
|
||||
** ascending base address. It uses a bubble sort algorithm.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void FirmwareSortSegments(void)
|
||||
{
|
||||
tFirmwareSegment * currentSegment;
|
||||
uint32_t i;
|
||||
uint32_t tempBase;
|
||||
uint32_t tempLength;
|
||||
uint8_t *tempData;
|
||||
|
||||
/* Only continue if the list is not empty and has at least 2 segments. */
|
||||
if (FirmwareGetSegmentCount() > 1)
|
||||
{
|
||||
/* Repeat bubbling for the total amount of segments - 1. */
|
||||
for (i = 1; i < FirmwareGetSegmentCount(); i++)
|
||||
{
|
||||
/* Beging at the start of the list. */
|
||||
currentSegment = segmentList;
|
||||
while ( (currentSegment != NULL) && (currentSegment->next != NULL) )
|
||||
{
|
||||
/* Is the first one's base address higher then the next one's? */
|
||||
if (currentSegment->base > currentSegment->next->base)
|
||||
{
|
||||
/* Swap the contents of these segments, excluding the next and prev fields. */
|
||||
tempBase = currentSegment->next->base;
|
||||
tempLength = currentSegment->next->length;
|
||||
tempData = currentSegment->next->data;
|
||||
currentSegment->next->base = currentSegment->base;
|
||||
currentSegment->next->length = currentSegment->length;
|
||||
currentSegment->next->data = currentSegment->data;
|
||||
currentSegment->base = tempBase;
|
||||
currentSegment->length = tempLength;
|
||||
currentSegment->data = tempData;
|
||||
}
|
||||
/* Continue with the next pair. */
|
||||
currentSegment = currentSegment->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /*** end of FirmwareSortSegments ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Helper function to merge the segments in the linked list. When the firmware
|
||||
** data in two adjacent segments also holds an adjacent range, then the
|
||||
** firmware data from both segments are combined into one new one. Note that
|
||||
** this function only works properly if the segments are already ordered. For
|
||||
** this reasonse, the segments are explicitely sorted at the start.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void FirmwareMergeSegments(void)
|
||||
{
|
||||
tFirmwareSegment * currentSegment;
|
||||
tFirmwareSegment * removeSegment;
|
||||
|
||||
/* Only continue if the list is not empty and has at least 2 segments. */
|
||||
if (FirmwareGetSegmentCount() > 1)
|
||||
{
|
||||
/* This function only works properly if the segments are correctly ordered. Perform
|
||||
* sorting here to make sure this is the case.
|
||||
*/
|
||||
FirmwareSortSegments();
|
||||
/* Begin as the start of the linked list. */
|
||||
currentSegment = segmentList;
|
||||
/* Iterate through the segments until the end of the list. */
|
||||
while ( (currentSegment != NULL) && (currentSegment->next != NULL) )
|
||||
{
|
||||
/* Are these segments adjacent? */
|
||||
if ((currentSegment->base + currentSegment->length) == currentSegment->next->base)
|
||||
{
|
||||
/* Increase the size of the allocated data array such that it can hold the data
|
||||
* of both segments.
|
||||
*/
|
||||
currentSegment->data = realloc(currentSegment->data, currentSegment->length +
|
||||
currentSegment->next->length);
|
||||
/* Assert reallocation. */
|
||||
assert(currentSegment->data != NULL);
|
||||
/* Only continue if reallocation was successful. */
|
||||
if (currentSegment->data != NULL)
|
||||
{
|
||||
/* Append the data from the next segment. */
|
||||
memcpy(&(currentSegment->data[currentSegment->length]),
|
||||
currentSegment->next->data, currentSegment->next->length);
|
||||
currentSegment->length += currentSegment->next->length;
|
||||
/* Store the segment pointer that should be removed. */
|
||||
removeSegment = currentSegment->next;
|
||||
/* Remove the segment now that is has been merged with the previous one. */
|
||||
FirmwareDeleteSegment(removeSegment);
|
||||
/* After removing the current segment's higher address sibling we have a new
|
||||
* sibling. This one could also be adjacent and in need of merging. So do not
|
||||
* update the currentSegment pointer to the next one. Instead repeat the loop
|
||||
* iteration for the same currentSegment pointer. We just need to check that
|
||||
* the new sibling is actually there and not the end of the list. This would
|
||||
* cause a problem when accessing currentSegment->next in the while-loop
|
||||
* condition. If there is no sibling, then we can simply stop the loop because
|
||||
* merging is all done then.
|
||||
*/
|
||||
if (currentSegment->next == NULL)
|
||||
{
|
||||
/* End of the linked list reached. Merging is done. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Merge skipped due to memory allocation issue. Just continue with the next
|
||||
* segment then.
|
||||
*/
|
||||
currentSegment = currentSegment->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Continue with the next one. */
|
||||
currentSegment = currentSegment->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /*** end of FirmwareMergeSegments ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Helper function to obtain the first memory address of the firmware data
|
||||
** that is present in the linked list with segments.
|
||||
** \return The first memory address.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static uint32_t FirmwareGetFirstAddress(void)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
tFirmwareSegment * firstSegment;
|
||||
|
||||
/* Obtain first segment in the linked list. */
|
||||
firstSegment = FirmwareGetSegment(0u);
|
||||
/* Sanity check. Make sure a valid segment was found. */
|
||||
assert(firstSegment != NULL);
|
||||
/* Only continue if a valid segment was found. */
|
||||
if (firstSegment != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Set the first address in this segment as the result. */
|
||||
result = firstSegment->base;
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of FirmwareGetFirstAddress ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Helper function to obtain the last memory address of the firmware data
|
||||
** that is present in the linked list with segments.
|
||||
** \return The last memory address.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static uint32_t FirmwareGetLastAddress(void)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
tFirmwareSegment * lastSegment;
|
||||
|
||||
/* Obtain last segment in the linked list. */
|
||||
lastSegment = FirmwareGetSegment(FirmwareGetSegmentCount() - 1u);
|
||||
/* Sanity check. Make sure a valid segment was found. */
|
||||
assert(lastSegment != NULL);
|
||||
/* Only continue if a valid segment was found. */
|
||||
if (lastSegment != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Calculate the last address in this segment. */
|
||||
result = lastSegment->base + lastSegment->length - 1u;
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of FirmwareGetLastAddress ***/
|
||||
|
||||
|
||||
/*********************************** end of firmware.c *********************************/
|
|
@ -0,0 +1,101 @@
|
|||
/************************************************************************************//**
|
||||
* \file firmware.h
|
||||
* \brief Firmware data module header file.
|
||||
* \ingroup Firmware
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
* \defgroup Firmware Firmware Data Module
|
||||
* \brief Module with functionality to load, manipulate and store firmware data.
|
||||
* \ingroup Library
|
||||
* \details
|
||||
* The Firmwarwe Data module contains functionality to load, manipulate and store firmware
|
||||
* data. It contains an interface for linking firmware file parsers that handle the
|
||||
* loading and saving the firmware data from and to a file in the correct format. For
|
||||
* example the Motorola S-record format.
|
||||
****************************************************************************************/
|
||||
#ifndef FIRMWARE_H
|
||||
#define FIRMWARE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Groups information together of a firmware segment, such that it can be used
|
||||
* as a node in a linked list.
|
||||
*/
|
||||
typedef struct t_firmware_segment
|
||||
{
|
||||
/** \brief Start memory address of the segment. */
|
||||
uint32_t base;
|
||||
/** \brief Number of data bytes in the segment. */
|
||||
uint32_t length;
|
||||
/** \brief Pointer to array with the segment's data bytes. */
|
||||
uint8_t *data;
|
||||
/** \brief Pointer to the previous node, or NULL if it is the first one. */
|
||||
struct t_firmware_segment * prev;
|
||||
/** \brief Pointer to the next node, or NULL if it is the last one. */
|
||||
struct t_firmware_segment * next;
|
||||
} tFirmwareSegment;
|
||||
|
||||
/** \brief Firmware file parser. */
|
||||
typedef struct t_firmware_parser
|
||||
{
|
||||
/** \brief Extract the firmware segments from the firmware file and add them as nodes
|
||||
* to the linked list.
|
||||
*/
|
||||
bool (* LoadFromFile) (char const * firmwareFile);
|
||||
/** \brief Write all the firmware segments from the linked list to the specified
|
||||
* firmware file.
|
||||
*/
|
||||
bool (* SaveToFile) (char const * firmwareFile);
|
||||
} tFirmwareParser;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
void FirmwareInit(tFirmwareParser const * parser);
|
||||
void FirmwareTerminate(void);
|
||||
bool FirmwareLoadFromFile(char const * firmwareFile);
|
||||
bool FirmwareSaveToFile(char const * firmwareFile);
|
||||
uint32_t FirmwareGetSegmentCount(void);
|
||||
tFirmwareSegment * FirmwareGetSegment(uint32_t segmentIdx);
|
||||
bool FirmwareAddData(uint32_t address, uint32_t len, uint8_t const * data);
|
||||
bool FirmwareRemoveData(uint32_t address, uint32_t len);
|
||||
void FirmwareClearData(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FIRMWARE_H */
|
||||
/********************************* end of firmware.h ***********************************/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifndef CO_GCC_H_
|
||||
#define CO_GCC_H_
|
||||
/*lint -save -w1 */
|
||||
|
||||
#ifdef _lint /* Make sure no compiler comes this way */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Standard library headers typically define the assert macro so that it
|
||||
expands to a complicated conditional expression that uses special
|
||||
funtions that Lint does not know about by default. For linting
|
||||
purposes, we can simplify things a bit by forcing assert() to expand to
|
||||
a call to a special function that has the appropriate 'assert'
|
||||
semantics.
|
||||
*/
|
||||
//lint -function( __assert, __lint_assert )
|
||||
void __lint_assert( int );
|
||||
//lint ++d"assert(e)=__lint_assert(!!(e))"
|
||||
//(++d makes this definition permanently immutable for the Lint run.)
|
||||
//Now that we've made our own 'assert', we need to keep people from being
|
||||
//punished when the marco in 'assert.h' appears not to be used:
|
||||
//lint -efile(766,*assert.h)
|
||||
|
||||
typedef char *__builtin_va_list;
|
||||
|
||||
/*lint -e{171} */
|
||||
__builtin_va_list __lint_init_va(...);
|
||||
|
||||
void __builtin_va_end( __builtin_va_list );
|
||||
/*lint
|
||||
++d"__builtin_va_start(ap,parmN)=((ap)=__lint_init_va(parmN))"
|
||||
++d"__builtin_va_arg(a,b)=(*( ((b) *) ( (((a) += sizeof(b)) - sizeof(b) )))"
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
The headers included below must be generated; For C++, generate
|
||||
with:
|
||||
|
||||
g++ [usual build options] -E -dM t.cpp >lint_cppmac.h
|
||||
|
||||
For C, generate with:
|
||||
|
||||
gcc [usual build options] -E -dM t.c >lint_cmac.h
|
||||
|
||||
...where "t.cpp" and "t.c" are empty source files.
|
||||
|
||||
It's important to use the same compiler options used when compiling
|
||||
project code because they can affect the existence and precise
|
||||
definitions of certain predefined macros. See gcc-readme.txt for
|
||||
details and a tutorial.
|
||||
*/
|
||||
#if defined(__cplusplus)
|
||||
# include "lint_cppmac.h" // DO NOT COMMENT THIS OUT. DO NOT SUPPRESS ERROR 322. (If you see an error here, your Lint configuration is broken; check -i options and ensure that you have generated lint_cppmac.h as documented in gcc-readme.txt. Otherwise Gimpel Software cannot support your configuration.)
|
||||
#else
|
||||
# include "lint_cmac.h" // DO NOT COMMENT THIS OUT. DO NOT SUPPRESS ERROR 322. (If you see an error here, your Lint configuration is broken; check -i options and ensure that you have generated lint_cmac.h as documented in gcc-readme.txt. Otherwise Gimpel Software cannot support your configuration.)
|
||||
#endif
|
||||
|
||||
/* If the macro set given by the generated macro files must be adjusted in
|
||||
order for Lint to cope, then you can make those adjustments here.
|
||||
*/
|
||||
|
||||
#define LINT_CO_GCC_H_GCC_VERSION ( __GNUC__ * 10000 + \
|
||||
__GNUC_MINOR__ * 100 + \
|
||||
__GNUC_PATCHLEVEL__ )
|
||||
|
||||
/* The following is a workaround for versions of GCC with bug 25717, in
|
||||
which the preprocessor does not dump a #define directive for __STDC__
|
||||
when -dM is given:
|
||||
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25717
|
||||
|
||||
We know the unconditional definition of __STDC__ was introduced no
|
||||
later than version 3.0; the preprocessor bug was fixed no later than
|
||||
version 4.1.0.
|
||||
*/
|
||||
#if ( LINT_CO_GCC_H_GCC_VERSION >= 30000 && \
|
||||
LINT_CO_GCC_H_GCC_VERSION < 40100 )
|
||||
# define __STDC__ 1
|
||||
#endif
|
||||
|
||||
#if !__cplusplus && !__STRICT_ANSI__ && __STDC_VERSION__ < 199901L
|
||||
/* apparently, the code is compiled with -std=gnu89 (as opposed to -std=c89),
|
||||
so: */
|
||||
/*lint -rw_asgn(inline,__inline) */
|
||||
#endif
|
||||
|
||||
#if LINT_CO_GCC_H_GCC_VERSION >= 40300
|
||||
# define __COUNTER__ __lint__COUNTER__
|
||||
//lint +rw( *type_traits ) // Enable type traits support
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#if _lint >= 909 // For 9.00i and later:
|
||||
//// __attribute__ is GCC's __attribute__:
|
||||
//
|
||||
//lint -rw_asgn(__attribute__,__gcc_attribute__)
|
||||
//lint -rw_asgn(__attribute, __gcc_attribute__)
|
||||
//
|
||||
//// Prevent "__attribute__" from being defined as a macro:
|
||||
//
|
||||
//lint --u"__attribute__"
|
||||
//lint --u"__attribute"
|
||||
//
|
||||
//// Because an attribute-specifier is a form of
|
||||
//// declaration-modifier, and because it can appear at the
|
||||
//// beginning of a decl-specifier-seq, we must enable "Early
|
||||
//// Modifiers":
|
||||
//
|
||||
//lint +fem
|
||||
#else // for 9.00h and earlier:
|
||||
//lint -d__attribute__()=
|
||||
//lint -d__attribute()=
|
||||
#endif
|
||||
|
||||
#endif /* _lint */
|
||||
/*lint -restore */
|
||||
#endif /* CO_GCC_H_ */
|
|
@ -0,0 +1,209 @@
|
|||
/* Date Stamp */ -d"_lint_co_gcc_lnt=co-gcc.lnt modified 12-Jun-2014"
|
||||
/* To document usage use: -message( "Using " _lint_co_gcc_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
/* co-gcc.lnt: This is the seed file for configuring Lint for use with
|
||||
GCC versions 2.95.3 and later.
|
||||
|
||||
Like all compiler options files this file is intended to be used
|
||||
as follows:
|
||||
|
||||
lint co-gcc.lnt source-files-to-be-linted
|
||||
|
||||
Some of the information that co-gcc.lnt requires needs to be furnished
|
||||
with the help of the gcc system itself. The easiest way to generate
|
||||
this information is to use the makefile co-gcc.mak (supplied with the
|
||||
Lint distribution) in an invocation of GNU Make; for details, see the
|
||||
commentary at the top of co-gcc.mak.
|
||||
*/
|
||||
|
||||
-cgnu // Notifies FlexeLint that gcc is being used.
|
||||
|
||||
// ===========================
|
||||
// Preprocessor Configuration:
|
||||
+fdi // GCC starts its #include search in the directory of the including
|
||||
// file.
|
||||
|
||||
++fln // Allow:
|
||||
// # digit-sequence " [s-char-sequence] " new-line
|
||||
// as a synonym for:
|
||||
// # line digit-sequence " [s-char-sequence] " new-line
|
||||
// GCC additionally allows flag values to follow the
|
||||
// s-char-sequence, but currently Lint ignores them.
|
||||
|
||||
-header(co-gcc.h) // Includes headers generated by GCC (bringing in
|
||||
// predefined macros).
|
||||
+libh(co-gcc.h) // Marks that header as library code.
|
||||
|
||||
gcc-include-path.lnt // This .lnt file should contain --i options
|
||||
// and should be generated by invoking gcc with its '-v' option.
|
||||
// (GCC's implicit #include search path is presented in the output.)
|
||||
// This happens automatically when 'make -f co-gcc.mak' is invoked.
|
||||
|
||||
// Assertion directives (a feature of GCC's preprocessor) have been
|
||||
// considered obsolete in GCC's documentation since version 3.0, so we do
|
||||
// not use them here. If support for #assert is needed in the form of a
|
||||
// lint option, one may use '-a#' like so:
|
||||
// -a#machine(i386) // #assert's machine(i386) (SVR4 facility).
|
||||
|
||||
// File extensions:
|
||||
// From the GCC man page:
|
||||
//
|
||||
// file.cc
|
||||
// file.cp
|
||||
// file.cxx
|
||||
// file.cpp
|
||||
// file.CPP
|
||||
// file.c++
|
||||
// file.C
|
||||
// C++ source code that must be preprocessed. Note that in .cxx, the
|
||||
// last two letters must both be literally x. Likewise, .C refers to
|
||||
// a literal capital C.
|
||||
//
|
||||
// We emulate this with:
|
||||
|
||||
+cpp(.cc)
|
||||
+cpp(.cp)
|
||||
+cpp(.cxx)
|
||||
+cpp(.cpp)
|
||||
+cpp(.c++)
|
||||
// Note the exceptions:
|
||||
// +cpp(.CPP)
|
||||
// +cpp(.C)
|
||||
// These are commented out for the default config because they seem to
|
||||
// cause trouble more often than not. For starters, it is problematic
|
||||
// with filesystems that are case-insensitive (which has become common
|
||||
// even on some POSIX systems).
|
||||
|
||||
// =============
|
||||
// Size Options:
|
||||
// +fwc // wchar_t might be builtin; if so, uncomment this option. (NOTE:
|
||||
// // this option needs to be set before a size option is given for
|
||||
// // wchar_t; see the documentation for -sw# in the Lint manual.)
|
||||
|
||||
size-options.lnt // This .lnt file should be generated (preferrably
|
||||
// by a program created by invoking GCC with the compile options that
|
||||
// are used in the compilation of the project to be linted). This
|
||||
// happens automatically when 'make -f co-gcc.mak' is invoked.
|
||||
|
||||
|
||||
// ===========================================
|
||||
// +rw and -d options to cope with GNU syntax:
|
||||
+ppw(ident) // Tolerate #ident
|
||||
+ppw(warning)
|
||||
|
||||
// GCC provides alternative spellings of certain keywords:
|
||||
+rw(__inline)
|
||||
-rw_asgn(__inline__,__inline)
|
||||
-rw_asgn(__header_always_inline,__inline)
|
||||
-rw_asgn(__header_inline,__inline)
|
||||
|
||||
-rw_asgn(__signed__,signed)
|
||||
-rw_asgn(__signed,signed)
|
||||
-rw_asgn( __volatile__, volatile )
|
||||
-rw_asgn( __volatile, volatile )
|
||||
+rw(restrict)
|
||||
-rw_asgn(__restrict,restrict)
|
||||
-rw_asgn(__restrict__,restrict)
|
||||
++d"__const=const" // gconv.h uses __const rather than const
|
||||
++d"const=const" // ensure const expands to const.
|
||||
|
||||
-rw_asgn( asm, _up_to_brackets )
|
||||
-rw_asgn( __asm, _up_to_brackets )
|
||||
-rw_asgn( __asm__, _up_to_brackets )
|
||||
// This re-definition of the various spellings of the asm keyword enables
|
||||
// Lint to pass gracefully over expression-statements like:
|
||||
// __asm __volatile ("fsqrt" : "=t" (__result) : "0" (__x));
|
||||
// But it may be necessary to suppress certain error messages that are
|
||||
// triggered by tokens that are part of an assembly declaration or
|
||||
// statement. For example:
|
||||
|
||||
-d"__asm__(p...)=/*lint -e{19}*/ __asm__(p)"
|
||||
|
||||
// ...causes Lint to be quiet about the semicolon that follows an
|
||||
// __asm__() declaration. Note, the -e{N} form of suppression takes
|
||||
// effect only for the forward-declaration, definition or
|
||||
// [possibly-compound] statement that immediately follows. Because a
|
||||
// semicolon is seen as a declaration-terminator, Error 19 will be
|
||||
// re-enabled immediately after the semicolon in '__asm__(...);'.
|
||||
// (The elipsis after the macro parameter p allows zero or more commas to
|
||||
// appear in the operand.)
|
||||
//
|
||||
// If you encounter other diagnostics that appear to need suppression in
|
||||
// or near assembly regions, please let us know!
|
||||
//
|
||||
-esym(123,__asm__)
|
||||
|
||||
-rw_asgn(__alignof__,__alignof)
|
||||
|
||||
// "__extension__" is GCC's way of allowing the use of non-standard
|
||||
// constructs in a strict Standard-conforming mode. We don't currently
|
||||
// have explicit support for it, but we can use local suppressions. For
|
||||
// example, we can use -e(160) so that we will not see any Errors about
|
||||
// GNU statement-expressions wrapped in __extension__().
|
||||
++d"__extension__=/*lint -e(160) */"
|
||||
|
||||
++d"__null=0"
|
||||
+rw(_to_semi) // needed for the two macros above.
|
||||
+rw(__typeof__) // activate __typeof__ keyword
|
||||
-d"__typeof=__typeof__" // an alternative to using __typeof__
|
||||
|
||||
-rw(__except) // This MS reserved word is used as an identifier
|
||||
+rw( __complex__, __real__, __imag__ ) // reserved words that can be ignored.
|
||||
++d"__builtin_strchr=(char*)" // permits the inline definition ...
|
||||
++d"__builtin_strpbrk=(char*)" // of these functions to be linted ...
|
||||
++d"__builtin_strrchr=(char*)" // without drawing a complaint
|
||||
++d"__builtin_strstr=(char*)" // about the use of a non-standard name
|
||||
++d"__PRETTY_FUNCTION__=___function___" // lint defines ___function___ internally
|
||||
++d"__FUNCTION__=___function___" // lint defines ___function___ internally
|
||||
++d"__func__=___function___" // Some C++ modes suport the implicit __func__
|
||||
// identifier.
|
||||
-ident($)
|
||||
|
||||
// =========================================================
|
||||
// Other options supporting GNU C/C++ syntax:
|
||||
+fld // enables the processing of _L_abel _D_esignators E.g.:
|
||||
// union { double d; int i; } u = { d: 3.141 };
|
||||
|
||||
// =========================================================
|
||||
// Generally useful suppressions:
|
||||
-wlib(1) // sets the warning level within library headers to 1
|
||||
// (no warnings, just syntax errors). Comment out if you
|
||||
// are actually linting library headers.
|
||||
-elib(123) // 123 is really a warning, but it's in the "Error" range.
|
||||
-elib(93) // allow newlines within quoted string arguments to macros
|
||||
-elib(46) // allow bit fields to have integral types other than
|
||||
// '_Bool' and 'int'.
|
||||
-elibsym(628) // Suppress 628 for __builtin symbols.
|
||||
|
||||
-esym(528,__huge_val,__nan,__qnan,__qnanf,__snan,__snanf)
|
||||
// We don't care if we don't reference some GNU functions
|
||||
-esym(528,__gnu_malloc,__gnu_calloc)
|
||||
|
||||
// The following functions exhibit variable return modes.
|
||||
// That is, they may equally-usefully be called for a value
|
||||
// as called just for their effects. Accordingly we inhibit
|
||||
// Warning 534 for these functions.
|
||||
// Feel free to add to or subtract from this list.
|
||||
|
||||
-esym(534,close,creat,fclose,fprintf,fputc)
|
||||
-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)
|
||||
-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)
|
||||
-esym(534,strncat,strncpy,unlink,write)
|
||||
|
||||
// For non-ANSI compilers we suppress messages 515 and 516
|
||||
// for functions known to have variable argument lists.
|
||||
// For ANSI compilers, header files should take care of this.
|
||||
|
||||
-esym(515,fprintf,printf,sprintf,fscanf,scanf,sscanf)
|
||||
-esym(516,fprintf,printf,sprintf,fscanf,scanf,sscanf)
|
||||
-esym(1702,*operator<<,*operator>>)
|
||||
-esym(534,*operator<<,*operator>>)
|
||||
-esym(1055,*__builtin*)
|
||||
-esym(718,*__builtin*) // The compiler does not need these ...
|
||||
-esym(746,*__builtin*) // declared and it knows their prototypes.
|
|
@ -0,0 +1,5 @@
|
|||
--i/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/include
|
||||
--i/usr/local/include
|
||||
--i/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/include-fixed
|
||||
--i/usr/include
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
|
||||
Using FlexeLint with GCC
|
||||
|
||||
These notes describe how to use the option file co-gcc.lnt which serves
|
||||
as a replacement for the older co-gnu.lnt and co-gnu3.lnt options files.
|
||||
|
||||
--- Quick Start ---
|
||||
|
||||
If you just want a quick-and-dirty Lint configuration (one that enables
|
||||
you to use Standard Library headers and system headers) then use the
|
||||
makefile 'co-gcc.mak' (supplied with the Lint distribution) in an
|
||||
invocation of GNU Make like so:
|
||||
|
||||
make -f co-gcc.mak
|
||||
|
||||
... which should generate the following files (provided that 'gcc', 'g++'
|
||||
and 'awk' are each found in your $PATH):
|
||||
|
||||
lint_cmac.h
|
||||
lint_cppmac.h
|
||||
gcc-include-path.lnt
|
||||
size-options.lnt
|
||||
|
||||
(co-gcc.lnt depends on these files, so they must be generated before you
|
||||
do anything else.)
|
||||
|
||||
That's it! You should now be able to run:
|
||||
|
||||
flint co-gcc.lnt [source files]
|
||||
|
||||
Note that Lint must be able to find co-gcc.lnt and the files referenced
|
||||
therein. If you want to keep them in a separate directory (e.g.,
|
||||
/usr/local/etc/flint) from the one where you will invoke Lint (e.g.,
|
||||
~/some-project/src), you'll need to specify the former with a '-i' option
|
||||
so that Lint will know where to look. In that case, the invocation would
|
||||
look like:
|
||||
|
||||
flint -i /usr/local/etc/flint co-gcc.lnt [source files]
|
||||
|
||||
If your project is compiled without any explicit command-line switches
|
||||
other than '-c' then this invocation alone might be all that you need to
|
||||
get started linting your project. Otherwise it probably won't suffice.
|
||||
For a Lint configuration that better matches the way you compile your
|
||||
code, you should at least read the 'usage' note at the top of co-gcc.mak.
|
||||
|
||||
For a motivation for the contents of co-gcc.mak, and to better understand
|
||||
the configuration issues in general, please read on.
|
||||
|
||||
--- Introduction ---
|
||||
|
||||
The configuration of Lint for use with GCC-compiled sources is complicated
|
||||
by two major issues:
|
||||
|
||||
First, GCC defines a large number of preprocessor macros internally (i.e.,
|
||||
it defines a lot of macros for which there are no '#define' directives in
|
||||
any source file that Lint can read.). Unless this issue is resolved for
|
||||
each project, Lint will not see the same sequence of C/C++ tokens as GCC
|
||||
when it tries to analyze your program, and as a result it will not see the
|
||||
same set of declarations; consequently you'll see lots of spurious
|
||||
messages because the analysis will reflect that of a program that is
|
||||
truly ill-formed (unlike the program seen by GCC).
|
||||
|
||||
Second, GCC is aware of several built-in functions. Most of them can be
|
||||
presented to Lint as ordinary forward-declarations of functions so as to
|
||||
avoid undesired diagnostics claiming that these functions were not
|
||||
declared before the first point of use. Note, these declarations do not
|
||||
necessarily need to be presented to GCC.
|
||||
|
||||
--- Solving the Preprocessor Problem ---
|
||||
|
||||
Before we get started, we'll need an empty C source file. Call it
|
||||
'empty.c' and save it to disk. Next, use your favorite command
|
||||
interpreter environment (such as sh in Unix-like environments or cmd.exe
|
||||
on Windows) and go to the directory containing 'empty.c'. Verify that you
|
||||
can run GCC by doing the following:
|
||||
|
||||
gcc -v
|
||||
|
||||
If your environment is properly set up you should see a version string.
|
||||
(You'll also want to verify that this is the same GCC executable used to
|
||||
compile your sources; check the PATH environment variable or try running
|
||||
'which gcc'.)
|
||||
|
||||
Assuming that worked, you can now try the following (and note that case,
|
||||
as with C/C++ identifiers, is important.):
|
||||
|
||||
gcc -E -dM empty.c
|
||||
|
||||
On one system, we then see definitions like:
|
||||
|
||||
#define __DBL_MIN_EXP__ (-1021)
|
||||
#define __FLT_MIN__ 1.17549435e-38F
|
||||
#define __DEC64_DEN__ 0.000000000000001E-383DD
|
||||
|
||||
... followed by about a hundred more '#define' directives. What just
|
||||
happened? We passed two options to gcc; the first one, '-E', means,
|
||||
"don't run the compiler; just run the preprocessor". The option '-dM'
|
||||
(not to be confused with '-DM', which is completely different) means,
|
||||
"don't generate preprocessor output; instead, only dump all macro
|
||||
definitions, including those defined internally".
|
||||
|
||||
With this output, we are now halfway to the point of having a preprocessor
|
||||
configuration for Lint. First, let's redirect those macros to a file:
|
||||
|
||||
gcc -E -dM empty.c >lint_cmac.h
|
||||
|
||||
Next, let's test our configuration: make a simple C source file
|
||||
containing the "Hello, world" program in a file called 't.c' (in the same
|
||||
directory as 'empty.c')
|
||||
|
||||
#include <stdio.h>
|
||||
int main () {
|
||||
printf( "hello, world!\n" );
|
||||
}
|
||||
|
||||
To lint this program, first copy the lnt file (co-gcc.lnt) and the
|
||||
associated header (co-gcc.h) into the same directory. Next, create two
|
||||
new empty files:
|
||||
|
||||
size-options.lnt
|
||||
gcc-include-path.lnt
|
||||
|
||||
... and save them to disk. Then make a file called 'std.lnt' which will
|
||||
(at first) contain only:
|
||||
|
||||
co-gcc.lnt
|
||||
|
||||
This tells Lint, "process the arguments in co-gcc.lnt". Two of those
|
||||
arguments are:
|
||||
|
||||
-header(co-gcc.h) // #include's headers generated by GCC.
|
||||
+libh(co-gcc.h) // Marks co-gcc.h as library code.
|
||||
|
||||
'-header(co-gcc.h)' means "behave as if each primary source file began
|
||||
with '#include "co-gcc.h"'. (Note that co-gcc.h includes "lint_cmac.h"
|
||||
when Lint runs in C language mode.)
|
||||
|
||||
Finally, try running:
|
||||
|
||||
/path/to/flint std.lnt t.c
|
||||
|
||||
... or, on Windows:
|
||||
|
||||
[drive-letter]:\path\to\lint-nt std.lnt t.c
|
||||
|
||||
Next we'll see output similar to the following:
|
||||
|
||||
FlexeLint for C/C++ (Unix/386) Vers. 9.00c, Copyright Gimpel Software
|
||||
1985-2009
|
||||
|
||||
--- Module: t.c (C)
|
||||
_
|
||||
#include <stdio.h>
|
||||
t.c 3 Error 322: Unable to open include file 'stdio.h'
|
||||
|
||||
What went wrong? The problem is that we haven't yet addressed the other
|
||||
half of the preprocessor configuration, namely: the ordered sequence of
|
||||
directories to search for system headers. Fortunately GCC already knows
|
||||
this list and gives us a way to discover it. Just run:
|
||||
|
||||
gcc -c -v empty.c
|
||||
|
||||
On one system (specifically, Mac OS X on Intel), that yields a lot of
|
||||
verbose output including these lines:
|
||||
|
||||
#include "..." search starts here:
|
||||
#include <...> search starts here:
|
||||
/usr/local/include
|
||||
/usr/lib/gcc/i686-apple-darwin8/4.0.1/include
|
||||
/usr/include
|
||||
/System/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
End of search list.
|
||||
|
||||
(Naturally, that list will look a bit different in different
|
||||
environments.) To make Lint search for system headers in the same way, we
|
||||
need to take that output from GCC and use it to make a set of options of
|
||||
the form --i[directory]. E.g. on the same system, that means that in
|
||||
gcc-include-path.lnt, I should place the following --i options:
|
||||
|
||||
--i/usr/local/include
|
||||
--i/usr/lib/gcc/i686-apple-darwin8/4.0.1/include
|
||||
--i/usr/include
|
||||
--i/System/Library/Frameworks
|
||||
--i/Library/Frameworks
|
||||
|
||||
(Note, arguments to Lint are processed in order, so the --i options must
|
||||
appear before t.c or they will not take effect in time.)
|
||||
|
||||
In this case, none of the directory names contains a space, but if one of
|
||||
them did we would have to surround its name with quotes as in:
|
||||
|
||||
--i"/usr/local/include"
|
||||
|
||||
Now let's try linting "hello, world" again:
|
||||
|
||||
/path/to/flint std.lnt t.c
|
||||
|
||||
This time we should see no error messages. Are we done yet? Not quite.
|
||||
First, let's test our configuration against all of the C Standard Library
|
||||
headers. Modify t.c to:
|
||||
|
||||
#include <assert.h>
|
||||
#include <iso646.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <wctype.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int main () {
|
||||
printf( "hello, world!\n" );
|
||||
}
|
||||
|
||||
|
||||
... and try linting again:
|
||||
|
||||
/path/to/flint std.lnt t.c
|
||||
|
||||
This time you should see a number of messages; in particular, you should
|
||||
see Info 766 issued for most of these headers since they were not used.
|
||||
you may also see some legitimate warnings, and you may see an Error or two
|
||||
about 'wchar_t'. (Note, if it seems as though your port of GCC recognizes
|
||||
wchar_t as a keyword instead of an identifier then uncomment the use of
|
||||
'+fwc' in your copy of co-gcc.lnt).
|
||||
|
||||
[NOTE: we should point out that the option -wlib(1) is in co-gcc.lnt for a
|
||||
reason. Please note that we *strongly* recommend against the use of
|
||||
options like -wlib(0) or -elib(*). If you see syntax error messages about
|
||||
library header code, odds are that something is wrong with the Lint
|
||||
configuration; so you'll do yourself no favors by silencing Lint when it
|
||||
sees constructs that Lint's parser doesn't know how to handle. If you need
|
||||
help with correcting your configuration, please check the Lint manual or
|
||||
contact us.]
|
||||
|
||||
We should really be done now, right? Well, not quite. A remaining issue
|
||||
is that the set of predefined macros (dumped into "lint_cmac.h" earlier)
|
||||
depends not only on things like the target system and the version of GCC;
|
||||
it also depends on the options that you pass to GCC when you compile your
|
||||
program. E.g., if we invoke:
|
||||
|
||||
gcc -O3 -E -dM empty.c >lint_cmac.h
|
||||
|
||||
... then (with the version of GCC we tested) lint_cmac.h will no longer
|
||||
contain a definition for the macro '__NO_INLINE__' and contains a new
|
||||
definition for '__OPTIMIZE__'. So when you generate macros, you should be
|
||||
careful to pass in the full set of options used when you compile.
|
||||
Ideally, you should establish a target in your build system that
|
||||
re-generates the predefined macro header whenever your build configuration
|
||||
changes; that way you'll seldom need to think about it again and Lint's
|
||||
preprocessor configuration will always match the compiler's.
|
||||
|
||||
Assuming you've generated the right set of predefined macros for your
|
||||
build settings, you should now try Linting a single primary source file in
|
||||
your project. Since we're just starting out, let's run with -w1 (i.e.,
|
||||
with the warning level set to one) so that we can deal with any syntax
|
||||
errors that pop up:
|
||||
|
||||
flint std.lnt -u -w1 some-project-file.c
|
||||
|
||||
Again, remember that syntax errors at this stage are likely due to a
|
||||
misconfiguration; please check the Lint manual for likely remedies or
|
||||
contact us if the solution is not obvious.
|
||||
|
||||
Once you've taken care of all syntax errors, try doing the same with all
|
||||
project files. We recommend placing the name of each project file in a
|
||||
.lnt file (often called project.lnt); e.g.:
|
||||
|
||||
file1.c
|
||||
file2.c
|
||||
[...etc.]
|
||||
|
||||
... and invoke Lint like so:
|
||||
|
||||
flint std.lnt -w1 project.lnt
|
||||
|
||||
When all syntax errors are resolved, you can begin turning on Warning
|
||||
messages (i.e., those listed in section 17.4 of the Lint manual). You can
|
||||
turn them on individually after '-w1' or you can instead use '-w2' and
|
||||
then suppress the Warnings that are less severe. (For details on message
|
||||
suppression, see section 5.2 of the Lint manual.)
|
||||
|
||||
At this point, you should be well-equipped to Lint any C program compiled
|
||||
with GCC. However, C++ users have a couple more points to consider.
|
||||
|
||||
The command used to invoke GCC also affects the set of predefined macros.
|
||||
Observe the difference in '#define' output when you invoke:
|
||||
|
||||
g++ -O3 -E -dM empty.c >lint_cppmac.h
|
||||
diff lint_cmac.h lint_cppmac.h
|
||||
|
||||
Also, note that the list of directories to search for Standard Library
|
||||
headers has some new additions when you use 'g++ -v -c empty.c' instead of
|
||||
'gcc -v -c empty.c'. Your sequence of --i options should be set
|
||||
accordingly.
|
||||
|
||||
That's about it for the preprocessor.
|
||||
|
||||
--- Size options ---
|
||||
|
||||
Finally, you'll need to establish sizes of primitive types. E.g. for a
|
||||
64-bit platform this includes setting '-sp8' (indicating that pointers are
|
||||
8 bytes wide). It often also involves setting '-sl8' (indicating that
|
||||
'long' is eight bytes wide). As suggested earlier, the makefile
|
||||
co-gcc.mak can generate these options for you.
|
||||
|
||||
If you find this tutorial to be lacking in some way, please contact us
|
||||
(support@gimpel.com) with your suggestions for improvement.
|
|
@ -0,0 +1,250 @@
|
|||
#define __DBL_MIN_EXP__ (-1021)
|
||||
#define __UINT_LEAST16_MAX__ 0xffff
|
||||
#define __ATOMIC_ACQUIRE 2
|
||||
#define __FLT_MIN__ 1.17549435082228750797e-38F
|
||||
#define __GCC_IEC_559_COMPLEX 2
|
||||
#define __UINT_LEAST8_TYPE__ unsigned char
|
||||
#define __SIZEOF_FLOAT80__ 16
|
||||
#define __INTMAX_C(c) c ## L
|
||||
#define __CHAR_BIT__ 8
|
||||
#define __UINT8_MAX__ 0xff
|
||||
#define __WINT_MAX__ 0xffffffffU
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#define __SIZE_MAX__ 0xffffffffffffffffUL
|
||||
#define __WCHAR_MAX__ 0x7fffffff
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
|
||||
#define __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L)
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
|
||||
#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
|
||||
#define __GCC_IEC_559 2
|
||||
#define __FLT_EVAL_METHOD__ 0
|
||||
#define __unix__ 1
|
||||
#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||
#define __x86_64 1
|
||||
#define __UINT_FAST64_MAX__ 0xffffffffffffffffUL
|
||||
#define __SIG_ATOMIC_TYPE__ int
|
||||
#define __DBL_MIN_10_EXP__ (-307)
|
||||
#define __FINITE_MATH_ONLY__ 0
|
||||
#define __GNUC_PATCHLEVEL__ 1
|
||||
#define __UINT_FAST8_MAX__ 0xff
|
||||
#define __has_include(STR) __has_include__(STR)
|
||||
#define __DEC64_MAX_EXP__ 385
|
||||
#define __INT8_C(c) c
|
||||
#define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL
|
||||
#define __SHRT_MAX__ 0x7fff
|
||||
#define __LDBL_MAX__ 1.18973149535723176502e+4932L
|
||||
#define __UINT_LEAST8_MAX__ 0xff
|
||||
#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
|
||||
#define __UINTMAX_TYPE__ long unsigned int
|
||||
#define __linux 1
|
||||
#define __DEC32_EPSILON__ 1E-6DF
|
||||
#define __unix 1
|
||||
#define __UINT32_MAX__ 0xffffffffU
|
||||
#define __LDBL_MAX_EXP__ 16384
|
||||
#define __WINT_MIN__ 0U
|
||||
#define __linux__ 1
|
||||
#define __SCHAR_MAX__ 0x7f
|
||||
#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
|
||||
#define __INT64_C(c) c ## L
|
||||
#define __DBL_DIG__ 15
|
||||
#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
|
||||
#define __SIZEOF_INT__ 4
|
||||
#define __SIZEOF_POINTER__ 8
|
||||
#define __USER_LABEL_PREFIX__
|
||||
#define __STDC_HOSTED__ 1
|
||||
#define __LDBL_HAS_INFINITY__ 1
|
||||
#define __FLT_EPSILON__ 1.19209289550781250000e-7F
|
||||
#define __LDBL_MIN__ 3.36210314311209350626e-4932L
|
||||
#define __STDC_UTF_16__ 1
|
||||
#define __DEC32_MAX__ 9.999999E96DF
|
||||
#define __INT32_MAX__ 0x7fffffff
|
||||
#define __SIZEOF_LONG__ 8
|
||||
#define __STDC_IEC_559__ 1
|
||||
#define __STDC_ISO_10646__ 201505L
|
||||
#define __UINT16_C(c) c
|
||||
#define __DECIMAL_DIG__ 21
|
||||
#define __gnu_linux__ 1
|
||||
#define __has_include_next(STR) __has_include_next__(STR)
|
||||
#define __LDBL_HAS_QUIET_NAN__ 1
|
||||
#define __GNUC__ 6
|
||||
#define __MMX__ 1
|
||||
#define __FLT_HAS_DENORM__ 1
|
||||
#define __SIZEOF_LONG_DOUBLE__ 16
|
||||
#define __BIGGEST_ALIGNMENT__ 16
|
||||
#define __DBL_MAX__ ((double)1.79769313486231570815e+308L)
|
||||
#define __INT_FAST32_MAX__ 0x7fffffffffffffffL
|
||||
#define __DBL_HAS_INFINITY__ 1
|
||||
#define __DEC32_MIN_EXP__ (-94)
|
||||
#define __INT_FAST16_TYPE__ long int
|
||||
#define __LDBL_HAS_DENORM__ 1
|
||||
#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
|
||||
#define __INT_LEAST32_MAX__ 0x7fffffff
|
||||
#define __DEC32_MIN__ 1E-95DF
|
||||
#define __DBL_MAX_EXP__ 1024
|
||||
#define __DEC128_EPSILON__ 1E-33DL
|
||||
#define __SSE2_MATH__ 1
|
||||
#define __ATOMIC_HLE_RELEASE 131072
|
||||
#define __PTRDIFF_MAX__ 0x7fffffffffffffffL
|
||||
#define __amd64 1
|
||||
#define __STDC_NO_THREADS__ 1
|
||||
#define __ATOMIC_HLE_ACQUIRE 65536
|
||||
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
|
||||
#define __SIZEOF_SIZE_T__ 8
|
||||
#define __SIZEOF_WINT_T__ 4
|
||||
#define __GCC_HAVE_DWARF2_CFI_ASM 1
|
||||
#define __GXX_ABI_VERSION 1010
|
||||
#define __FLT_MIN_EXP__ (-125)
|
||||
#define __INT_FAST64_TYPE__ long int
|
||||
#define __DBL_MIN__ ((double)2.22507385850720138309e-308L)
|
||||
#define __LP64__ 1
|
||||
#define __DECIMAL_BID_FORMAT__ 1
|
||||
#define __DEC128_MIN__ 1E-6143DL
|
||||
#define __REGISTER_PREFIX__
|
||||
#define __UINT16_MAX__ 0xffff
|
||||
#define __DBL_HAS_DENORM__ 1
|
||||
#define __UINT8_TYPE__ unsigned char
|
||||
#define __NO_INLINE__ 1
|
||||
#define __FLT_MANT_DIG__ 24
|
||||
#define __VERSION__ "6.3.1 20170306"
|
||||
#define __UINT64_C(c) c ## UL
|
||||
#define _STDC_PREDEF_H 1
|
||||
#define __GCC_ATOMIC_INT_LOCK_FREE 2
|
||||
#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __STDC_IEC_559_COMPLEX__ 1
|
||||
#define __INT32_C(c) c
|
||||
#define __DEC64_EPSILON__ 1E-15DD
|
||||
#define __ORDER_PDP_ENDIAN__ 3412
|
||||
#define __DEC128_MIN_EXP__ (-6142)
|
||||
#define __INT_FAST32_TYPE__ long int
|
||||
#define __UINT_LEAST16_TYPE__ short unsigned int
|
||||
#define unix 1
|
||||
#define __INT16_MAX__ 0x7fff
|
||||
#define __SIZE_TYPE__ long unsigned int
|
||||
#define __UINT64_MAX__ 0xffffffffffffffffUL
|
||||
#define __INT8_TYPE__ signed char
|
||||
#define __ELF__ 1
|
||||
#define __GCC_ASM_FLAG_OUTPUTS__ 1
|
||||
#define __FLT_RADIX__ 2
|
||||
#define __INT_LEAST16_TYPE__ short int
|
||||
#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
|
||||
#define __UINTMAX_C(c) c ## UL
|
||||
#define __SSE_MATH__ 1
|
||||
#define __k8 1
|
||||
#define __SIG_ATOMIC_MAX__ 0x7fffffff
|
||||
#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||
#define __SIZEOF_PTRDIFF_T__ 8
|
||||
#define __x86_64__ 1
|
||||
#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
|
||||
#define __INT_FAST16_MAX__ 0x7fffffffffffffffL
|
||||
#define __UINT_FAST32_MAX__ 0xffffffffffffffffUL
|
||||
#define __UINT_LEAST64_TYPE__ long unsigned int
|
||||
#define __FLT_HAS_QUIET_NAN__ 1
|
||||
#define __FLT_MAX_10_EXP__ 38
|
||||
#define __LONG_MAX__ 0x7fffffffffffffffL
|
||||
#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
|
||||
#define __FLT_HAS_INFINITY__ 1
|
||||
#define __UINT_FAST16_TYPE__ long unsigned int
|
||||
#define __DEC64_MAX__ 9.999999999999999E384DD
|
||||
#define __CHAR16_TYPE__ short unsigned int
|
||||
#define __PRAGMA_REDEFINE_EXTNAME 1
|
||||
#define __SEG_FS 1
|
||||
#define __INT_LEAST16_MAX__ 0x7fff
|
||||
#define __DEC64_MANT_DIG__ 16
|
||||
#define __INT64_MAX__ 0x7fffffffffffffffL
|
||||
#define __UINT_LEAST32_MAX__ 0xffffffffU
|
||||
#define __SEG_GS 1
|
||||
#define __GCC_ATOMIC_LONG_LOCK_FREE 2
|
||||
#define __INT_LEAST64_TYPE__ long int
|
||||
#define __INT16_TYPE__ short int
|
||||
#define __INT_LEAST8_TYPE__ signed char
|
||||
#define __STDC_VERSION__ 201112L
|
||||
#define __DEC32_MAX_EXP__ 97
|
||||
#define __INT_FAST8_MAX__ 0x7f
|
||||
#define __INTPTR_MAX__ 0x7fffffffffffffffL
|
||||
#define linux 1
|
||||
#define __SSE2__ 1
|
||||
#define __LDBL_MANT_DIG__ 64
|
||||
#define __DBL_HAS_QUIET_NAN__ 1
|
||||
#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
|
||||
#define __code_model_small__ 1
|
||||
#define __k8__ 1
|
||||
#define __INTPTR_TYPE__ long int
|
||||
#define __UINT16_TYPE__ short unsigned int
|
||||
#define __WCHAR_TYPE__ int
|
||||
#define __SIZEOF_FLOAT__ 4
|
||||
#define __UINTPTR_MAX__ 0xffffffffffffffffUL
|
||||
#define __DEC64_MIN_EXP__ (-382)
|
||||
#define __INT_FAST64_MAX__ 0x7fffffffffffffffL
|
||||
#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
|
||||
#define __FLT_DIG__ 6
|
||||
#define __UINT_FAST64_TYPE__ long unsigned int
|
||||
#define __INT_MAX__ 0x7fffffff
|
||||
#define __amd64__ 1
|
||||
#define __INT64_TYPE__ long int
|
||||
#define __FLT_MAX_EXP__ 128
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#define __DBL_MANT_DIG__ 53
|
||||
#define __SIZEOF_FLOAT128__ 16
|
||||
#define __INT_LEAST64_MAX__ 0x7fffffffffffffffL
|
||||
#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||
#define __DEC64_MIN__ 1E-383DD
|
||||
#define __WINT_TYPE__ unsigned int
|
||||
#define __UINT_LEAST32_TYPE__ unsigned int
|
||||
#define __SIZEOF_SHORT__ 2
|
||||
#define __SSE__ 1
|
||||
#define __LDBL_MIN_EXP__ (-16381)
|
||||
#define __INT_LEAST8_MAX__ 0x7f
|
||||
#define __SIZEOF_INT128__ 16
|
||||
#define __LDBL_MAX_10_EXP__ 4932
|
||||
#define __ATOMIC_RELAXED 0
|
||||
#define __DBL_EPSILON__ ((double)2.22044604925031308085e-16L)
|
||||
#define _LP64 1
|
||||
#define __UINT8_C(c) c
|
||||
#define __INT_LEAST32_TYPE__ int
|
||||
#define __SIZEOF_WCHAR_T__ 4
|
||||
#define __UINT64_TYPE__ long unsigned int
|
||||
#define __INT_FAST8_TYPE__ signed char
|
||||
#define __GNUC_STDC_INLINE__ 1
|
||||
#define __DBL_DECIMAL_DIG__ 17
|
||||
#define __STDC_UTF_32__ 1
|
||||
#define __FXSR__ 1
|
||||
#define __DEC_EVAL_METHOD__ 2
|
||||
#define __UINT32_C(c) c ## U
|
||||
#define __INTMAX_MAX__ 0x7fffffffffffffffL
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __FLT_DENORM_MIN__ 1.40129846432481707092e-45F
|
||||
#define __INT8_MAX__ 0x7f
|
||||
#define __UINT_FAST32_TYPE__ long unsigned int
|
||||
#define __CHAR32_TYPE__ unsigned int
|
||||
#define __FLT_MAX__ 3.40282346638528859812e+38F
|
||||
#define __INT32_TYPE__ int
|
||||
#define __SIZEOF_DOUBLE__ 8
|
||||
#define __FLT_MIN_10_EXP__ (-37)
|
||||
#define __INTMAX_TYPE__ long int
|
||||
#define __DEC128_MAX_EXP__ 6145
|
||||
#define __ATOMIC_CONSUME 1
|
||||
#define __GNUC_MINOR__ 3
|
||||
#define __UINTMAX_MAX__ 0xffffffffffffffffUL
|
||||
#define __DEC32_MANT_DIG__ 7
|
||||
#define __DBL_MAX_10_EXP__ 308
|
||||
#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
|
||||
#define __INT16_C(c) c
|
||||
#define __STDC__ 1
|
||||
#define __PTRDIFF_TYPE__ long int
|
||||
#define __ATOMIC_SEQ_CST 5
|
||||
#define __UINT32_TYPE__ unsigned int
|
||||
#define __UINTPTR_TYPE__ long unsigned int
|
||||
#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
|
||||
#define __DEC128_MANT_DIG__ 34
|
||||
#define __LDBL_MIN_10_EXP__ (-4931)
|
||||
#define __SIZEOF_LONG_LONG__ 8
|
||||
#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
|
||||
#define __LDBL_DIG__ 18
|
||||
#define __FLT_DECIMAL_DIG__ 9
|
||||
#define __UINT_FAST16_MAX__ 0xffffffffffffffffUL
|
||||
#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
|
||||
#define __UINT_FAST8_TYPE__ unsigned char
|
||||
#define __ATOMIC_ACQ_REL 4
|
||||
#define __ATOMIC_RELEASE 3
|
|
@ -0,0 +1,85 @@
|
|||
# This file contains functions and configurations for generating PC-Lint build
|
||||
# targets for your CMake projects.
|
||||
|
||||
set(PC_LINT_EXECUTABLE "lint-nt.exe" CACHE STRING "full path to the pc-lint executable. NOT the generated lin.bat")
|
||||
set(PC_LINT_CONFIG_DIR "${PROJECT_SOURCE_DIR}/lint/gnu" CACHE STRING "full path to the directory containing pc-lint configuration files")
|
||||
set(PC_LINT_USER_FLAGS "-b" CACHE STRING "additional pc-lint command line options -- some flags of pc-lint cannot be set in option files (most notably -b)")
|
||||
|
||||
# a phony target which causes all available *_LINT targets to be executed
|
||||
add_custom_target(ALL_LINT)
|
||||
|
||||
# add_pc_lint(target source1 [source2 ...])
|
||||
#
|
||||
# Takes a list of source files and generates a build target which can be used
|
||||
# for linting all files
|
||||
#
|
||||
# The generated lint commands assume that a top-level config file named
|
||||
# 'std.lnt' resides in the configuration directory 'PC_LINT_CONFIG_DIR'. This
|
||||
# config file must include all other config files. This is standard lint
|
||||
# behaviour.
|
||||
#
|
||||
# Parameters:
|
||||
# - target: the name of the target to which the sources belong. You will get a
|
||||
# new build target named ${target}_LINT
|
||||
# - source1 ... : a list of source files to be linted. Just pass the same list
|
||||
# as you passed for add_executable or add_library. Everything except
|
||||
# C and CPP files (*.c, *.cpp, *.cxx) will be filtered out.
|
||||
#
|
||||
# Example:
|
||||
# If you have a CMakeLists.txt which generates an executable like this:
|
||||
#
|
||||
# set(MAIN_SOURCES main.c foo.c bar.c)
|
||||
# add_executable(main ${MAIN_SOURCES})
|
||||
#
|
||||
# include this file
|
||||
#
|
||||
# include(/path/to/pc_lint.cmake)
|
||||
#
|
||||
# and add a line to generate the main_LINT target
|
||||
#
|
||||
# if(COMMAND add_pc_lint)
|
||||
# add_pc_lint(main ${MAIN_SOURCES})
|
||||
# endif(COMMAND add_pc_lint)
|
||||
#
|
||||
function(add_pc_lint target)
|
||||
get_directory_property(lint_include_directories INCLUDE_DIRECTORIES)
|
||||
get_directory_property(lint_defines COMPILE_DEFINITIONS)
|
||||
|
||||
# let's get those elephants across the alps
|
||||
# prepend each include directory with "-i"; also quotes the directory
|
||||
set(lint_include_directories_transformed)
|
||||
foreach(include_dir ${lint_include_directories})
|
||||
list(APPEND lint_include_directories_transformed -i"${include_dir}")
|
||||
endforeach(include_dir)
|
||||
|
||||
# prepend each definition with "-d"
|
||||
set(lint_defines_transformed)
|
||||
foreach(definition ${lint_defines})
|
||||
list(APPEND lint_defines_transformed -d${definition})
|
||||
endforeach(definition)
|
||||
|
||||
# list of all commands, one for each given source file
|
||||
set(pc_lint_commands)
|
||||
|
||||
foreach(sourcefile ${ARGN})
|
||||
# only include c and cpp files
|
||||
if( sourcefile MATCHES \\.c$|\\.cxx$|\\.cpp$ )
|
||||
# make filename absolute
|
||||
get_filename_component(sourcefile_abs ${sourcefile} ABSOLUTE)
|
||||
# create command line for linting one source file and add it to the list of commands
|
||||
list(APPEND pc_lint_commands
|
||||
COMMAND ${PC_LINT_EXECUTABLE}
|
||||
-i"${PC_LINT_CONFIG_DIR}" std.lnt
|
||||
"-u" ${PC_LINT_USER_FLAGS}
|
||||
${lint_include_directories_transformed}
|
||||
${lint_defines_transformed}
|
||||
${sourcefile_abs})
|
||||
endif()
|
||||
endforeach(sourcefile)
|
||||
|
||||
# add a custom target consisting of all the commands generated above
|
||||
add_custom_target(${target}_LINT ${pc_lint_commands} VERBATIM)
|
||||
# make the ALL_LINT target depend on each and every *_LINT target
|
||||
add_dependencies(ALL_LINT ${target}_LINT)
|
||||
|
||||
endfunction(add_pc_lint)
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
co-gcc.lnt
|
|
@ -0,0 +1,42 @@
|
|||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifndef LINT_SUPPORT_CO_MSC100_H_
|
||||
#define LINT_SUPPORT_CO_MSC100_H_
|
||||
|
||||
// co-msc100.h --
|
||||
// This header is automatically included in every module if you use
|
||||
// co-msc100.lnt. (There is a -header(co-msc100.h) option therein
|
||||
// for this purpose.)
|
||||
|
||||
// Microsoft's C++11 implementation does not yet include built-in support
|
||||
// for the new character types, so we need to disable the relevant
|
||||
// keywords here. (This must be done before the inclusion of any other
|
||||
// header file because Microsoft's library headers contain declarations of
|
||||
// typedef names with the same spelling.)
|
||||
//lint -rw(char16_t,char32_t)
|
||||
|
||||
// Next we must compensate for the fact that class typeinfo is available
|
||||
// for use in the MSC compilers without an explicit definition. According
|
||||
// to the standard this class definition is not (available by default).
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#else // C mode
|
||||
|
||||
// co-msc100.lnt defines some macros that the Microsoft compiler defines
|
||||
// in C++ modes but not in C mode; we must un-define them here:
|
||||
#undef _CPPRTTI
|
||||
#undef _NATIVE_WCHAR_T_DEFINED
|
||||
#undef _WCHAR_T_DEFINED
|
||||
#undef _NATIVE_NULLPTR_SUPPORTED
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* LINT_SUPPORT_CO_MSC100_H_ */
|
|
@ -0,0 +1,461 @@
|
|||
/* Date Stamp */ -d"_lint_co_msc100_lnt=co-msc100.lnt modified 19-Sep-2013"
|
||||
/* To document usage use: -message( "Using " _lint_co_msc100_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
// co-msc100.lnt
|
||||
// Compiler Options for Visual Studio for C/C++ Version 10.00
|
||||
// (Visual Studio 2010)
|
||||
// This file contains options to allow PC-lint to process source
|
||||
// files for your compiler. It is used as follows:
|
||||
//
|
||||
// lint co-msc100.lnt source-file(s)
|
||||
//
|
||||
// (See macros-msc.c and/or macros-msc.cpp for details.)
|
||||
|
||||
// Section 1: options independent of the use of the automatic macro
|
||||
// generator (macros-msc.cpp)
|
||||
//
|
||||
-cmsc
|
||||
-A(C++2011)
|
||||
+compiler(search_actively_including_stack)
|
||||
-si4 // integers are 4 bytes
|
||||
-sp4 // pointers are 4 bytes too.
|
||||
|
||||
// We now support __declspec directly so that the following
|
||||
// option is now commented out. If trouble ensues you can
|
||||
// once again disable __declspec through this option.
|
||||
// -d__declspec()= // ignore this construct
|
||||
-d_declspec=__declspec // the single '_' version is occasionally used
|
||||
|
||||
// while processing compiler (library) header files ...
|
||||
-wlib(1) // sets the warning level within library headers to 1
|
||||
// (no warnings, just syntax errors). Comment out if you
|
||||
// are actually linting library headers. This
|
||||
// option makes obsolete options of the form -elib(axxx) where
|
||||
// xxx >= 400 which may be retained for historical reasons.
|
||||
-elib(1111) // Some VC++ headers contain explicit specializations at class
|
||||
// scope.
|
||||
-elib(19) // useless declarations (lone semicolons)
|
||||
-elib(123) // function-like macro name used as non macro
|
||||
-elib(652) // suppress message about #define of earlier declared symbols
|
||||
-elib(762) // suppress message about multiple identical declarations and
|
||||
-elib(760) // suppress message about multiple identical macro defs
|
||||
-elib(514) // allow #if <boolean> | <boolean>
|
||||
-elib(553) // undefined preprocessor variables assumed 0
|
||||
-elib(1081) // suspicious object argument to an object parameter
|
||||
-elib(726) // extraneous comma in enum definition
|
||||
-elib(157) // suppress message about no data may follow an incomplete array
|
||||
-elib(91) // suppress message about line exceeds 598 characters
|
||||
|
||||
// SREGS, WORDREGS, BYTEREGS are defined in both bios.h and dos.h
|
||||
// and accordingly you MAY get type differences based on 'origin'.
|
||||
// If so, use the following options:
|
||||
// -etd(origin)
|
||||
// -elib(770)
|
||||
|
||||
-format=%(%f(%l)\s:\s%)%t\s%n:\s%m
|
||||
// error format similar to MSC
|
||||
// Note that %c can also be used to specify column
|
||||
-e46 // allows bit-fields to be other than int or unsigned
|
||||
+fan // allow anonymous unions
|
||||
+fdi // Use directory of the including file
|
||||
+fbo // enable the bool type
|
||||
+fwm // wprintf format codes are not standard
|
||||
-fdh // do not append a .h to header names
|
||||
-esym(123,min,max) // allows users to use min, max as variables
|
||||
+rw(__inline) // activate the __inline keyword
|
||||
-rw_asgn(__nullptr,nullptr)
|
||||
-e19 // Suppress errors about lone semicolons
|
||||
+ppw(import) // activate #import
|
||||
-d_inline=__inline // _inline is the same as __inline
|
||||
-sld8 // sizeof(long double) is 8.
|
||||
-function(exit,_exit) // _exit() is like exit()
|
||||
-function(exit,_assert) // _assert() is like exit()
|
||||
-emacro(506,assert) // don't warn about constant value Boolean
|
||||
-emacro(734,putc) // don't complain about items being too large.
|
||||
-emacro(415,_FP_SEG) // access of out-of-bounds pointer
|
||||
-emacro(740,FP_SEG,FP_OFF) // unusual casts
|
||||
-emacro((???),va_arg) // the va_arg() macro can yield 415, 416, 661, 662
|
||||
// 796 and 797 (out-of-bounds errors).
|
||||
-emacro((???),va_start) // the same applies to va_start
|
||||
-emacro(413,offsetof) // use of NULL pointer creates a stir
|
||||
-emacro(545,offsetof) // addressing an array member is OK
|
||||
-emacro(845,RGB) // a common use of RGB uses a operator that produces a 0
|
||||
-e793 // inhibit 'ANSI limit reached' --
|
||||
// limits are impractically low with MSVC headers
|
||||
-esym(628,eof) // failure to provide argument information for eof()
|
||||
-esym(773,L_tmpnam) // defined with an unparenthesized '+'
|
||||
-esym(438,_acp) // USES_CONVERSION assigns to _acp.
|
||||
-emacro(571,__isascii) // don't warn about the unusual cast
|
||||
-emacro(522,UNREFERENCED_PARAMETER) // don't complain about a lack of
|
||||
// side-effects
|
||||
-emacro(648,CDN_*) // ignore unsigned overflow
|
||||
-emacro(648,OIVN_*) // ignore unsigned overflow
|
||||
-emacro(648,TTN_*) // ignore unsigned overflow
|
||||
-emacro(648,TVN_*) // ignore unsigned overflow
|
||||
-emacro(648,TBN_*) // ignore unsigned overflow
|
||||
|
||||
// The following functions exhibit variable return modes.
|
||||
// That is, they may equally-usefully be called for a value
|
||||
// as called just for their effects. Accordingly we inhibit
|
||||
// Warning 534 for these functions.
|
||||
// Feel free to add to or subtract from this list.
|
||||
|
||||
-esym(534,close,creat,fclose,fflush,_flsbuf,fprintf,fputc)
|
||||
-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)
|
||||
-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)
|
||||
-esym(534,strncat,strncpy,unlink,write)
|
||||
|
||||
// These are the wide char variants of printf-scanf family
|
||||
|
||||
-wprintf( 1, wprintf )
|
||||
-wprintf( 3, fwprintf, swprintf )
|
||||
-wscanf( 1, wscanf )
|
||||
-wscanf( 2, fwscanf, swscanf )
|
||||
|
||||
// These are substitutions for sprintf
|
||||
|
||||
-printf( 3, StringCbPrintfA )
|
||||
-printf( 3, StringCchPrintfA )
|
||||
-wprintf( 3, StringCbPrintfW )
|
||||
-wprintf( 3, StringCchPrintfW )
|
||||
|
||||
// The following options are used to adjust our function mimicry to
|
||||
// the actual library as provided by MS.
|
||||
|
||||
-function( wcstombs(1) ) // remove the check for a NULL first arg to wcstombs()
|
||||
|
||||
// The following options are required by most compilers to
|
||||
// noiselessly process iostream.h
|
||||
|
||||
-elib(1717) // empty prototypes
|
||||
-elib(522) // function return value ignored
|
||||
-elib(1053) // prototypes cannot be distinguished
|
||||
-elib(1721) // unusual operator =() declaration
|
||||
-elib(1720) // assignment op has non-const parameter
|
||||
-elib(655) // bitwise operator combining compatible enum's
|
||||
-elib(641) // converting enum's to int
|
||||
-elib(537) // repeated include file (ios.h)
|
||||
-elib(1511) // member (rdbuf) hides nonvirtual member
|
||||
-elib(1712) // default constructor not defined for class
|
||||
-elib(1736) // redundant access specifier
|
||||
-esym(1702,operator<<,operator>>) // both a member and an ordinary function
|
||||
|
||||
// These functions return things that are frequently ignored.
|
||||
|
||||
-esym(534,*operator<<,*operator>>)
|
||||
|
||||
// The following additional options seem to be needed.
|
||||
|
||||
-elib(506) // constant value Boolean
|
||||
-elib(620) // el or one? (some constants end in 'l' not 'L')
|
||||
-elib(648) // overflow in computing constant (3<<16)
|
||||
-elib(659) // nothing fold_NATIVE_WCHAR_T_DEFINEDlows '}' on some line
|
||||
-elib(723) // suspicious use of '='
|
||||
-elib(747) // significant prototype coercion
|
||||
-elib(740) // unusual pointer casts
|
||||
-elib(1007) // virtual functions within extern "C" block
|
||||
-elib(1029) // default argument repeated -- can't dist. char, signed char
|
||||
-elib(1055) // call to rdbuf() questioned?
|
||||
-elib(1504) // apparently useless structs
|
||||
-elib(1708,1709) // minor C/C++ declaration conflict
|
||||
-elib(1707) // operator new declared w/o 'static'
|
||||
-elib(1722) // assignment op does not return reference
|
||||
-elib(149) // default argument found in C code.
|
||||
-elib(578) // declaration of time hides delaration of global time().
|
||||
-elib(761) // two equivalent typedef declarations
|
||||
-elib(1065) // same name declared as "C" and not "C"
|
||||
-elib(1066) // same name declared as "C" and not "C"
|
||||
-elib(1704) // constructor with private access declaration
|
||||
-elib(1735) // default parameter within virtual function
|
||||
-elib(773) // macros that look like unparenthesized expressions
|
||||
-elib(806) // 1-bit bitfields typed int
|
||||
-elib(1501) // 0-length data members
|
||||
-elib(1510) // base class has no destructor
|
||||
-elib(1516) // data member hides inherited member
|
||||
-elib(1509) // base class destructor is not virtual
|
||||
|
||||
// Special Notice: You may be receiving mysterious 1058 errors
|
||||
// when you use "iomanipulator"s. For example:
|
||||
// cout << setw(4) << 4;
|
||||
// results in Error 1058 (assigning a const to a ref) because the
|
||||
// manipulator setw returns a non-lvalue which is assigned to a reference.
|
||||
// This reflects an oversight in the Microsoft header file: iomanip.h
|
||||
// Therein you may change the declaration:
|
||||
// friend ostream& operator<<(iostream& s, IOMANIP(T) & sm) { ...
|
||||
// to:
|
||||
// friend ostream& operator<<(iostream& s, const IOMANIP(T) & sm) { ...
|
||||
// to reflect the fact that sm is not modified by this function.
|
||||
|
||||
+fll // enable long long
|
||||
|
||||
// In the following option we define __uuidof() and suppress
|
||||
// Errors 50 and 69 and 1924 in exprs. containing same
|
||||
-d"__uuidof()= /*lint --e(50,69,1924) */ (_GUID)0"
|
||||
|
||||
-esym(123,FD_SET) // defined as macro and as typedef
|
||||
-esym(1726,endl,ends) // taking the address of an overloaded function
|
||||
-esym(18,Data_t::Data_t) // definition not matching declaration
|
||||
|
||||
-elib(10) // expecting ')' -- comdef.h has a: #if defined( id
|
||||
-elib(43) // vacuous array within _MIDL_FORMAT_STRING
|
||||
-elib(602) // benign comment within comment
|
||||
-elib(657) // declaring "anonymous struct" in union _LARGE_INTEGER
|
||||
-elib(799) // long numerical constant for max. __int64
|
||||
-elib(1502) // nothrow has no data members
|
||||
-elib(1505) // no access specifier in base class specifier
|
||||
-elib(1515) // AFX_THREAD_STATE member has no default constructor
|
||||
-elib(1706) // Unusual declaration with a scope operator
|
||||
-elib(1725) // data member is a reference
|
||||
-elib(1548) // conflicting exception specifications
|
||||
-elib(1737) // hiding global operator new
|
||||
-elib(1739) // binary operator should be non-member function
|
||||
-elib(1748) // non-virtual base class included twice
|
||||
-elib(1759) // post-fix operator returns a reference
|
||||
|
||||
// Add elements of ole automation
|
||||
|
||||
lib-ole.lnt
|
||||
|
||||
// Options required for .net
|
||||
|
||||
-d_stdcall=__stdcall // make _stdcall equivalent to __stdcall
|
||||
-d__interface=class // treat an interface the same as a class
|
||||
-d__unaligned= // pass over the __unaligned keyword
|
||||
-d__w64= // ignore this identifier
|
||||
-esym(40,DLGPROC) // used before being defined
|
||||
-elib(146) // assuming binary constant
|
||||
-elib(1015) // GetDefaultThreads not found in class
|
||||
+ppw(using) // ignore #using for now.
|
||||
|
||||
-d__pragma(x)= // ignore the pragma extension
|
||||
+rw(__ptr64) // additional qualifier
|
||||
+rw_asgn(__thiscall,fortran) // additional qualifier
|
||||
|
||||
-"d__identifier(x)=___identifier x"
|
||||
// treat C++ keyword x as an identifier
|
||||
|
||||
-elibsym(1512) // base class destructor not virtual
|
||||
|
||||
-d__TIMESTAMP__="Mon Jan 01 00:00:00 2010"
|
||||
-d__COUNTER__=__lint__COUNTER__
|
||||
-d__FUNCDNAME__="MyFunc"
|
||||
-d__FUNCSIG__="MyFunc"
|
||||
-d__FUNCTION__=___function___
|
||||
|
||||
-dinitonly= // Compiler should catch miss-uses.
|
||||
// Lint can just skip over it.
|
||||
-"dliteral=static const" // Documentation says they are
|
||||
// equivalent for member data.
|
||||
|
||||
// __try_cast is like dynamic_cast (except the former throws where
|
||||
// the latter returns 0).
|
||||
|
||||
-d__try_cast=dynamic_cast
|
||||
|
||||
+rw(__restrict) // reserved word
|
||||
|
||||
// Partial support for the "old" (VC++ 2003) Managed Extensions
|
||||
// syntax:
|
||||
+rw( __gc, __value, __nogc, __pin, __ptr32, __ptr64 )
|
||||
|
||||
-$ // $ can be used in identifiers
|
||||
+rw( __allowed_on_parameter )
|
||||
+rw( __allowed_on_function )
|
||||
+rw( __allowed_on_typedecl )
|
||||
+rw( __allowed_on_return )
|
||||
+rw( __allowed_on_struct )
|
||||
+rw( __allowed_on_function_or_typedecl )
|
||||
+rw( __allowed_on_field )
|
||||
+rw( __allowed_on_parameter_or_return )
|
||||
+rw( __allowed_on_function )
|
||||
+rw( *type_traits ) //type traits support
|
||||
|
||||
+e1942 // This Elective Note alerts the user to the non-standard
|
||||
// way in which MS handles originally-dependent base classes.
|
||||
// E.g. template<class T> class A : T { ... x ... };
|
||||
// Should T be searched for "x" during instantiation?
|
||||
// the standard says "no", MS does.
|
||||
|
||||
|
||||
-header(co-msc100.h) // implicitly includes <typeinfo>. (Needed because
|
||||
// MSVC 9 implicitly declares class type_info.)
|
||||
|
||||
|
||||
// Section 2: options that should be commented out if you use the
|
||||
// automatic macro generator (macros-msc.cpp)
|
||||
|
||||
// Note, a macro option of the form:
|
||||
// -dA{1}
|
||||
// has the same effect as:
|
||||
// -dA=1
|
||||
// or:
|
||||
// -d"A=1"
|
||||
// The curly-brace version of the syntax is appropriate for
|
||||
// macro-scavenging (the method we used to generate the macro options
|
||||
// below). For details, see notes on the -scavenge() option in section
|
||||
// 5.8.3 in the Lint manual. See also the macro generator file,
|
||||
// macros-msc.cpp, which follows the form of -scavenge() output.
|
||||
|
||||
// We generated the options in this section with the following commands:
|
||||
// %VSInstallDir%\vc\bin\vcvars32.bat
|
||||
// cl /EP /C macros-msc.cpp
|
||||
// The options for other build configurations will probably differ (which
|
||||
// is why you should comment out the following if you use the macro
|
||||
// generator).
|
||||
|
||||
// Also note: some of the following are defined for C++ mode but not for C
|
||||
// mode; but there's no need to comment them out here because they are
|
||||
// conditionally #undef'd in co-msc100.h.
|
||||
|
||||
-d_CPPRTTI{1}
|
||||
//
|
||||
// Defined for code compiled with /GR (Enable Run-Time Type
|
||||
// Information).
|
||||
//
|
||||
|
||||
-d_INTEGRAL_MAX_BITS{64}
|
||||
//
|
||||
// Reports the maximum size (in bits) for an integral type.
|
||||
//
|
||||
|
||||
// NOTE:
|
||||
// When generating 64-bit code, the definition for _M_IX86 must be
|
||||
// commented out.
|
||||
-d_M_IX86{600}
|
||||
//
|
||||
// Defined for x86 processors. See the "Values for _M_IX86 table" (in
|
||||
// Microsoft's preprocessor documentation) for more information. This
|
||||
// is not defined for x64 processors.
|
||||
//
|
||||
|
||||
-d_M_IX86_FP{0}
|
||||
//
|
||||
// Expands to a value indicating which /arch compiler option was used:
|
||||
//
|
||||
// 0 if /arch was not used.
|
||||
//
|
||||
// 1 if /arch:SSE was used.
|
||||
//
|
||||
// 2 if /arch:SSE2 was used.
|
||||
//
|
||||
// See /arch (Minimum CPU Architecture) for more information.
|
||||
//
|
||||
|
||||
-d_MSC_BUILD{1}
|
||||
//
|
||||
// Evaluates to the revision number component of the compiler's
|
||||
// version number. The revision number is the fourth component of the
|
||||
// period-delimited version number. For example, if the version number
|
||||
// of the Visual C++ compiler is 15.00.20706.01, the _MSC_BUILD macro
|
||||
// evaluates to 1.
|
||||
//
|
||||
|
||||
-d_MSC_EXTENSIONS{1}
|
||||
//
|
||||
// This macro is defined when you compile with the /Ze compiler option
|
||||
// (the default). Its value, when defined, is 1.
|
||||
//
|
||||
|
||||
-d_MSC_FULL_VER{160030319}
|
||||
//
|
||||
// Evaluates to the major, minor, and build number components of the
|
||||
// compiler's version number. The major number is the first component
|
||||
// of the period-delimited version number, the minor number is the
|
||||
// second component, and the build number is the third component. For
|
||||
// example, if the version number of the Visual C++ compiler is
|
||||
// 15.00.20706.01, the _MSC_FULL_VER macro evaluates to 150020706.
|
||||
// Type cl /? at the command line to view the compiler's version
|
||||
// number.
|
||||
//
|
||||
|
||||
-d_MSC_VER{1600}
|
||||
//
|
||||
// Evaluates to the major and minor number components of the
|
||||
// compiler's version number. The major number is the first component
|
||||
// of the period-delimited version number and the minor number is the
|
||||
// second component.
|
||||
//
|
||||
// For example, if the version number of the Visual C++ compiler is
|
||||
// 15.00.20706.01, the _MSC_VER macro evaluates to 1500.
|
||||
//
|
||||
// In Visual Studio 2010, _MSC_VER is defined as 1600.
|
||||
//
|
||||
|
||||
-d_MT{1}
|
||||
//
|
||||
// Defined when /MD or /MDd (Multithreaded DLL) or /MT or /MTd
|
||||
// (Multithreaded) is specified.
|
||||
//
|
||||
|
||||
-d_NATIVE_WCHAR_T_DEFINED{1}
|
||||
//
|
||||
// Defined when /Zc:wchar_t is used.
|
||||
//
|
||||
|
||||
-d_WCHAR_T_DEFINED{1}
|
||||
//
|
||||
// Defined when /Zc:wchar_t is used or if wchar_t is defined in a
|
||||
// system header file included in your project.
|
||||
//
|
||||
|
||||
-d_WIN32{1}
|
||||
//
|
||||
// Defined for applications for Win32 and Win64. Always defined.
|
||||
//
|
||||
|
||||
/**** Undocumented predefined macros follow ****/
|
||||
|
||||
-d_NATIVE_NULLPTR_SUPPORTED{1}
|
||||
|
||||
// Section 3: options that should remain commented out if you use the
|
||||
// automatic macro generator (macros-msc.cpp)
|
||||
|
||||
// When compiling with /J, use:
|
||||
//+fcu // Plain char is unsigned
|
||||
//-d_CHAR_UNSIGNED
|
||||
|
||||
// When compiling with /clr, /clr:pure or /clr:safe, use:
|
||||
//-d__cplusplus_cli=200406 // for all 3
|
||||
//-d_M_CEE_PURE // for /clr:pure
|
||||
//-d_M_CEE_SAFE // for /clr:safe
|
||||
//-d_MANAGED // for /clr
|
||||
|
||||
// When using any /clr form, use:
|
||||
//-d_M_CEE
|
||||
|
||||
|
||||
// When compiling with /GX or /EH, use:
|
||||
//-d_CPPUNWIND // Enable Exception Handling
|
||||
|
||||
// When compiling for Win64, use:
|
||||
//-d_WIN64
|
||||
|
||||
// When compiling with /Wp64, use:
|
||||
//-d_Wp64 // 64-bit portability
|
||||
|
||||
// Be sure to define your platform if any of the following apply:
|
||||
//-d_M_ALPHA // For DEC ALPHA platforms
|
||||
//-d_M_IA64 // For Itanium 64-bit processors
|
||||
//-d_M_X64 // For x64 processors
|
||||
|
||||
// When compiling with the /RTC option, use:
|
||||
//-d__MSVC_RUNTIME_CHECKS // Using such checks
|
||||
|
||||
// When compiling with /openmp, use:
|
||||
//-d_OPENMP=200203 // OpenMP specification date
|
||||
|
||||
// When compiling with /Zl, use:
|
||||
//-d_VC_NODEFAULTLIB // Omit default library name in *.obj file
|
||||
|
||||
/* DLL's or Multithreads? Enable the following:
|
||||
|
||||
-d_AFXDLL // making a DLL
|
||||
-d_DLL // ditto
|
||||
|
||||
*/
|
|
@ -0,0 +1,221 @@
|
|||
/* Date Stamp */ -d"_lint_env_vc10_lnt=env-vc10.lnt modified 22-Feb-2012"
|
||||
/* To document usage use: -message( "Using " _lint_env_vc10_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
/*
|
||||
env-vc10.lnt: environment parameters for Microsoft's Visual C++ 10.0
|
||||
|
||||
If you are using Microsoft Visual Studio 2010 and you wish to invoke
|
||||
PC-lint from that environment then add one or more commands to the
|
||||
Tools menu as follows.
|
||||
|
||||
Simple Check
|
||||
------------
|
||||
|
||||
For example, to add a simple facility to lint the current file you
|
||||
may do the following:
|
||||
|
||||
1. From the Tools Menu choose "External Tools ..."
|
||||
2. Click the "Add" button.
|
||||
3. You will now be able to enter the fields of this Tool.
|
||||
Modify them so that they approximate the following:
|
||||
|
||||
Title: PC-lint (Simple Check)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments:
|
||||
-i"c:\lint" std.lnt env-vc10.lnt "$(ItemFileName)$(ItemExt)"
|
||||
Initial Directory: $(ItemDir)
|
||||
|
||||
X_Use Output Window __Prompt for arguments __Close on exit
|
||||
|
||||
Please note that you will have to change the "Command:" path if
|
||||
the PC-lint Installation Directory is anything other than c:\lint
|
||||
and you will have to change the "Arguments:" line if the
|
||||
Configuration Directory is anything other than c:\lint
|
||||
|
||||
4. Select OK to return to the main environment.
|
||||
|
||||
This will result in the Tools menu containing the additional item
|
||||
"PC-lint (Simple Check)". Checking 'X' on 'Use Output Window' is
|
||||
important because in this way you can advance from error to error
|
||||
using the F8 key (Shift F8 to reverse).
|
||||
|
||||
Strings of the form $(...) are called macros and can be typed in
|
||||
directly as shown or can be selected from a menu by clicking
|
||||
a right arrow in the dialog box. $(ItemFileName) refers to the
|
||||
file name of the currently edited file without its path and without
|
||||
its extension. $(ItemExt) is its extension. $(ItemDir) represents
|
||||
the file's directory.
|
||||
|
||||
You will probably want to advance your new tool upward into the
|
||||
initial position of all tools while you are testing and modifying the
|
||||
command. You can do this by using the "Move Up" button that appears
|
||||
on the External Tools dialog.
|
||||
|
||||
The benefits of using "Initial Directory" are that file-names in lint
|
||||
error messages will not be so long, and, also, this directory can
|
||||
contain a std.lnt that overrides the global std.lnt in the
|
||||
Configuration Directory.
|
||||
|
||||
This Simple Check is fine to check stand-alone modules but to check
|
||||
projects or to unit check modules that are in projects we need to
|
||||
go a bit further ...
|
||||
|
||||
Project Creation
|
||||
----------------
|
||||
|
||||
To lint an entire project we will need the names of all the modules
|
||||
in the project. Visual Studio keeps these names (as well as some
|
||||
appropriate options such as define options (-d...) and include options
|
||||
(-i...) in a file named NAME.vcproj in the current project directory.
|
||||
NAME is the name of the project and is identified by the macro
|
||||
$(TargetName). PC-lint can read the .vcproj file and generate the
|
||||
appropriate .lnt file. We recommend creating a tool for this purpose.
|
||||
For this tool follow the steps 1-4 doing exactly the same thing as
|
||||
above except in step 3, the information entered should be:
|
||||
|
||||
Title: PC-lint (Project Creation)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments: -v -os("$(TargetName).lnt") "$(ProjectFileName)"
|
||||
Init. Dir.: $(ProjectDir)
|
||||
|
||||
__Use Output Window __Prompt for arguments x_Close on exit
|
||||
|
||||
You will need to have an active project before this will work.
|
||||
If you don't already have one you can obtain an active project
|
||||
from the Solutions Explorer. You then click the newly added
|
||||
"PC-lint (Project Creation)" tool on the tools menu to create
|
||||
NAME.lnt.
|
||||
|
||||
The file created is an ASCII file and we recommend that you open it
|
||||
within the IDE and examine it for any obvious flaws. This is your
|
||||
chance to make any necessary modifications to the file as the process
|
||||
of conversion may be less than perfect.
|
||||
|
||||
Project Check
|
||||
-------------
|
||||
|
||||
Interestingly, by opening up the NAME.lnt file created above and
|
||||
running the Simple Check described earlier you have the equivalent
|
||||
of a full project check. However, we prefer to create a special
|
||||
Project Check tool.
|
||||
|
||||
Now that we have a project file we can create a new tool called
|
||||
"PC-lint (project check)". For this tool again follow steps 1-4 doing
|
||||
exactly the same thing as above except in step 3, the information
|
||||
entered should be:
|
||||
|
||||
Title: PC-lint (Project Check)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments: -i"c:\lint" std.lnt env-vc10.lnt "$(TargetName).lnt"
|
||||
Init. Dir.: $(ProjectDir)
|
||||
|
||||
X_Use Output Window __Prompt for arguments __Close on exit
|
||||
|
||||
Unit Check
|
||||
----------
|
||||
|
||||
You can almost do a unit check on any single module by using the
|
||||
Simple Check scheme suggested above. The only problems are that you
|
||||
will need a -u option and you will not have the benefit of any -d or
|
||||
-i options that have been placed into NAME.lnt created in the Project
|
||||
Creation step. For this reason we suggest the following tool for
|
||||
doing a unit check of any module that is part of a project and for
|
||||
which a .lnt project file has been generated.
|
||||
|
||||
Title: PC-lint (Unit Check)
|
||||
Command: c:\lint\lint-nt.exe
|
||||
Arguments:
|
||||
-i"c:\lint" std.lnt env-vc10.lnt --u "$(TargetName).lnt" "$(ItemPath)"
|
||||
|
||||
Init. Dir.: $(ProjectDir)
|
||||
|
||||
X_Use Output Window __Prompt for arguments __Close on exit
|
||||
|
||||
Note that $(ItemPath) will provide a complete path name and in the
|
||||
absence of a project.lnt file it would cause full path names to
|
||||
appear in messages. But a side effect of using the project file
|
||||
with the --u option means that we adopt the shorter names used
|
||||
in the project file.
|
||||
|
||||
Suppressing Messages
|
||||
----------- --------
|
||||
|
||||
Suppressing messages is normally done by adding message suppression
|
||||
options to a file. For example, -e550 will suppress message 550.
|
||||
There are numerous other options to suppress messages.
|
||||
|
||||
As the documentation indicates, the file
|
||||
|
||||
c:\lint\options.lnt
|
||||
|
||||
(where c:\lint\ is the Configuration Directory) is the presumed
|
||||
container of your overall suppression policy. (Note: options.lnt is
|
||||
referenced by std.lnt). Add a message suppression here and you will
|
||||
affect all linting employing that configuration.
|
||||
|
||||
To suppress messages for a particular project (or for all projects
|
||||
within a given project directory) you may do the following:
|
||||
Create a file std.lnt that is contained in the project directory.
|
||||
Make it refer back to the std.lnt in the Configuration Directory.
|
||||
Then add additional message suppression options or indeed any options
|
||||
you want. For example it might contain:
|
||||
|
||||
c:\lint\std.lnt // reference to original std.lnt
|
||||
-e550 // project-specific option
|
||||
|
||||
In this way suppression is limited to a particular project.
|
||||
|
||||
|
||||
Tool Bar
|
||||
--------
|
||||
|
||||
You also have the option of creating a PC-lint toolbar within your
|
||||
Visual C++ IDE. First, create one or more tools as described above.
|
||||
You will need to know the number(s) of the tool(s) you want to place
|
||||
on the tool bar. This can only be done by the painful and laborious
|
||||
task of counting. Using the list provided by "Tools"/"External
|
||||
Tools", jot down the numbers (starting with 1 at the top) of all the
|
||||
tools to be added to the tool bar. We recommend placing all the
|
||||
PC-lint tools on a single tool bar. Then select Customize from the
|
||||
Tools menu. Select the Toolbars tab and click the New... button.
|
||||
Give the Toolbar a name (E.g., PC-lint) in the dialog box provided
|
||||
and click "OK". Confirm that the new toolbar is now floating on
|
||||
the desktop and that a check has been placed in the check box next
|
||||
to the new toolbar name. Then click on the Commands tab and
|
||||
select the "Toolbar:" radio button. Open the drop down list and
|
||||
select "PC-Lint" from the choices. Click the "Add Command..."
|
||||
button to reveal the "Add Command" window. In the "Categories:"
|
||||
box scroll down to and select the "Tools" item. In the
|
||||
"Commands:" box scroll down to and select the appropriate
|
||||
"External Command" numbered item that corresponds to the desired
|
||||
PC-Lint command, then click the OK button to add the selected item
|
||||
to the PC-Lint toolbar. Repeat the "Add Command..." process for
|
||||
each desired PC-Lint command the you wish to place on the PC-Lint
|
||||
toolbar.
|
||||
|
||||
If you want to add a button image to the toolbar, you can choose one
|
||||
via the Modify Selection button. Click Close and you now have your
|
||||
own PC-lint for C/C++ button. (Note: If you change the location of
|
||||
the PC-lint menu item on the Tools menu, you will change the subscript
|
||||
and you will need to change the button(s) on the toolbar.)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
-"format=%(%F(%l):%) error %n: (%t -- %m)" // Messages will contain
|
||||
// file information (%F), the line number (%l), the
|
||||
// message number (%n), message type (%t) and message text (%m).
|
||||
|
||||
-hF2 // Make sure we ALWAYS provide file information ('F') and use 2
|
||||
// lines (one for the source line in error and one for the
|
||||
// message).
|
||||
|
||||
-width(0) // don't break messages at any particular width
|
||||
-t4 // Presume that tabs are every 4 stops
|
||||
//+e900 // issue a message at termination.
|
|
@ -0,0 +1,17 @@
|
|||
/* Date Stamp */ -d"_lint_lib_ole_lnt=lib-ole.lnt modified 23-Mar-2004"
|
||||
/* To document usage use: -message( "Using " _lint_lib_ole_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// BSTR functions (part of OLE Automation)
|
||||
|
||||
-sem( SysAllocString, @p == malloc(1p) || @p == 0, 1p )
|
||||
-sem( SysAllocStringByteLen, @P == malloc(2n+1) || @p == 0 )
|
||||
-sem( SysAllocStringLen, @p == malloc(2n+1) || @p == 0 )
|
||||
-sem( SysStringLen, 1p ? @n == 1p - 1 : @n == 0 )
|
||||
-function( free, SysFreeString )
|
|
@ -0,0 +1,56 @@
|
|||
/* Date Stamp */ -d"_lint_lib_w32_lnt=lib-w32.lnt modified 2-Mar-1999"
|
||||
/* To document usage use: -message( "Using " _lint_lib_w32_lnt ) */
|
||||
// ---------------------------------------------------------------------
|
||||
// This file is provided by Gimpel Software (www.gimpel.com) for use with
|
||||
// its products PC-lint and FlexeLint.
|
||||
//
|
||||
// Redistribution and use of this file, with or without modification, is
|
||||
// permitted provided that any such redistribution retains this notice.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// lib-w32.lnt
|
||||
// PC-lint Library Options File for 32-bit mode windows.h
|
||||
|
||||
-d__FLAT__
|
||||
-d_WIN32
|
||||
-si4
|
||||
-sp4
|
||||
-esym(14,pLocalHeap) // variable defined in windows.h
|
||||
-e740 // remove 'suspicious cast' messages because these must be
|
||||
// routinely done within Windows.
|
||||
-elib(46) // windows.h uses a BYTE as base of bit field.
|
||||
-e793 // windows breaks ANSI limits
|
||||
|
||||
// the following functions have their return value typically ignored.
|
||||
// add or subtract from this list as desired.
|
||||
-esym(534,RegisterClass,ShowWindow,TranslateMessage,DispatchMessage)
|
||||
-esym(534,DrawText,GetTextMetrics,ReleaseDC,TextOut,SetTextAlign)
|
||||
-esym(534,SetScrollPos,SelectObject,SetBkMode,SendMessage,MessageBox)
|
||||
-esym(534,MessageBoxA,MessageBoxW,PostMessageA,PostMessageW)
|
||||
-esym(534,PatBlt,DeleteDC,SetCapture,SetCursor,StretchBlt)
|
||||
-esym(534,Rectangle,MoveTo,LineTo,ShowCursor,MoveWindow,SetWindowWord)
|
||||
-esym(534,SetPixel,FillRect,DeleteObject,KillTimer,GetProfileString)
|
||||
-esym(534,SetWindowLong,SetFocus,SetBkColor,SetTextColor,SetBrushOrg)
|
||||
-esym(534,UnrealizeObject,_lclose,Polygon,FrameRect,LoadString)
|
||||
-esym(534,GetInstanceData,GlobalUnlock,FreeResource,LoadString)
|
||||
-esym(534,DrawIcon,AppendMenu,GetObject,CheckMenuItem,SetClassWord)
|
||||
-esym(534,EnableMenuItem,SetMenu,DestroyMenu,TrackPopupMenu)
|
||||
-esym(534,AnsiUpper,Arc,BeginPaint,BitBlt,ChangeClipboardChain,Chord)
|
||||
-esym(534,CloseClipboard,CombineRgn,DdeClientTransaction,DdeDisconnect)
|
||||
-esym(534,DdeFreeStringHandle,DdeGetData,DdeNameService,DdePostAdvise)
|
||||
-esym(534,DdeQueryString,DdeUninitialize,DeleteMenu,DeleteMetaFile)
|
||||
-esym(534,DestroyWindow,DialogBox,DPtoLP,Ellipse,EmptyClipboard,EnableWindow)
|
||||
-esym(534,EnumChildWindows,EnumWindows,Escape,GetClassName,GetDlgItemText)
|
||||
-esym(534,GetFileTitle,GetMenuString,GetStrings,GetSystemMenu,GetTextFace)
|
||||
-esym(534,GetWindowText,GlobalDeleteAtom,GlobalFree,GlobalGetAtomName)
|
||||
-esym(534,LocalFree,LocalUnlock,LockResource,lstrcpy,OpenClipboard)
|
||||
-esym(534,Pie,PlayMetaFile,PopFindNextText,PostDataMessage,PostMessage)
|
||||
-esym(534,RestoreDC,SaveDC,SelectClipRgn,SendDlgItemMessage,SetClipboardData)
|
||||
-esym(534,SetDIBitsToDevice,SetMapMode,SetMapperFlags,SetROP2,SetStretchBltMode)
|
||||
-esym(534,SetTextJustification,SetTimer,SetViewportExt,SetViewportOrg)
|
||||
-esym(534,SetWindowExt,SetWindowOrg,StretchDIBits,WinExec)
|
||||
|
||||
// Ignored parameters
|
||||
-esym(715,lpszCmdParam,lpszCmdLine)
|
||||
|
||||
-emacro(648,PSN_*) // ignore unsigned overflow (0-200U)
|
|
@ -0,0 +1,85 @@
|
|||
# This file contains functions and configurations for generating PC-Lint build
|
||||
# targets for your CMake projects.
|
||||
|
||||
set(PC_LINT_EXECUTABLE "C:/Lint/lint-nt.exe" CACHE STRING "full path to the pc-lint executable. NOT the generated lin.bat")
|
||||
set(PC_LINT_CONFIG_DIR "${PROJECT_SOURCE_DIR}/lint/msvc" CACHE STRING "full path to the directory containing pc-lint configuration files")
|
||||
set(PC_LINT_USER_FLAGS "-b" CACHE STRING "additional pc-lint command line options -- some flags of pc-lint cannot be set in option files (most notably -b)")
|
||||
|
||||
# a phony target which causes all available *_LINT targets to be executed
|
||||
add_custom_target(ALL_LINT)
|
||||
|
||||
# add_pc_lint(target source1 [source2 ...])
|
||||
#
|
||||
# Takes a list of source files and generates a build target which can be used
|
||||
# for linting all files
|
||||
#
|
||||
# The generated lint commands assume that a top-level config file named
|
||||
# 'std.lnt' resides in the configuration directory 'PC_LINT_CONFIG_DIR'. This
|
||||
# config file must include all other config files. This is standard lint
|
||||
# behaviour.
|
||||
#
|
||||
# Parameters:
|
||||
# - target: the name of the target to which the sources belong. You will get a
|
||||
# new build target named ${target}_LINT
|
||||
# - source1 ... : a list of source files to be linted. Just pass the same list
|
||||
# as you passed for add_executable or add_library. Everything except
|
||||
# C and CPP files (*.c, *.cpp, *.cxx) will be filtered out.
|
||||
#
|
||||
# Example:
|
||||
# If you have a CMakeLists.txt which generates an executable like this:
|
||||
#
|
||||
# set(MAIN_SOURCES main.c foo.c bar.c)
|
||||
# add_executable(main ${MAIN_SOURCES})
|
||||
#
|
||||
# include this file
|
||||
#
|
||||
# include(/path/to/pc_lint.cmake)
|
||||
#
|
||||
# and add a line to generate the main_LINT target
|
||||
#
|
||||
# if(COMMAND add_pc_lint)
|
||||
# add_pc_lint(main ${MAIN_SOURCES})
|
||||
# endif(COMMAND add_pc_lint)
|
||||
#
|
||||
function(add_pc_lint target)
|
||||
get_directory_property(lint_include_directories INCLUDE_DIRECTORIES)
|
||||
get_directory_property(lint_defines COMPILE_DEFINITIONS)
|
||||
|
||||
# let's get those elephants across the alps
|
||||
# prepend each include directory with "-i"; also quotes the directory
|
||||
set(lint_include_directories_transformed)
|
||||
foreach(include_dir ${lint_include_directories})
|
||||
list(APPEND lint_include_directories_transformed -i"${include_dir}")
|
||||
endforeach(include_dir)
|
||||
|
||||
# prepend each definition with "-d"
|
||||
set(lint_defines_transformed)
|
||||
foreach(definition ${lint_defines})
|
||||
list(APPEND lint_defines_transformed -d${definition})
|
||||
endforeach(definition)
|
||||
|
||||
# list of all commands, one for each given source file
|
||||
set(pc_lint_commands)
|
||||
|
||||
foreach(sourcefile ${ARGN})
|
||||
# only include c and cpp files
|
||||
if( sourcefile MATCHES \\.c$|\\.cxx$|\\.cpp$ )
|
||||
# make filename absolute
|
||||
get_filename_component(sourcefile_abs ${sourcefile} ABSOLUTE)
|
||||
# create command line for linting one source file and add it to the list of commands
|
||||
list(APPEND pc_lint_commands
|
||||
COMMAND ${PC_LINT_EXECUTABLE}
|
||||
-i"${PC_LINT_CONFIG_DIR}" std.lnt
|
||||
"-u" ${PC_LINT_USER_FLAGS}
|
||||
${lint_include_directories_transformed}
|
||||
${lint_defines_transformed}
|
||||
${sourcefile_abs})
|
||||
endif()
|
||||
endforeach(sourcefile)
|
||||
|
||||
# add a custom target consisting of all the commands generated above
|
||||
add_custom_target(${target}_LINT ${pc_lint_commands} VERBATIM)
|
||||
# make the ALL_LINT target depend on each and every *_LINT target
|
||||
add_dependencies(ALL_LINT ${target}_LINT)
|
||||
|
||||
endfunction(add_pc_lint)
|
|
@ -0,0 +1,4 @@
|
|||
co-msc100.lnt
|
||||
env-vc10.lnt
|
||||
lib-w32.lnt
|
||||
|
|
@ -0,0 +1,625 @@
|
|||
/************************************************************************************//**
|
||||
* \file openblt.c
|
||||
* \brief OpenBLT host library source file.
|
||||
* \ingroup Library
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include "openblt.h" /* OpenBLT host library */
|
||||
#include "util.h" /* Utility module */
|
||||
#include "firmware.h" /* Firmware data module */
|
||||
#include "srecparser.h" /* S-record parser */
|
||||
#include "session.h" /* Communication session module */
|
||||
#include "xcploader.h" /* XCP loader module */
|
||||
#include "xcptpuart.h" /* XCP UART transport layer */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/** \brief The version number of the library as an integer. The number has two digits
|
||||
* for major-, minor-, and build-version. Version 1.05.12 would for example be
|
||||
* 10512.
|
||||
*/
|
||||
#define BLT_VERSION_NUMBER (10000u)
|
||||
|
||||
/** \brief The version number of the library as a null-terminated string. */
|
||||
#define BLT_VERSION_STRING "1.00.00"
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local constant declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Constant null-terminated string with the version number of the library. */
|
||||
char const bltVersionString[] = BLT_VERSION_STRING;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* V E R S I O N I N F O R M A T I O N
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains the version number of the library as an integer. The number has two
|
||||
** digits for major-, minor-, and build-version. Version 1.05.12 would for
|
||||
** example return 10512.
|
||||
** \return Library version number as an integer.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltVersionGetNumber(void)
|
||||
{
|
||||
return BLT_VERSION_NUMBER;
|
||||
} /*** end of BltVersionGetNumber ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains the version number of the library as a null-terminated string.
|
||||
** Version 1.05.12 would for example return "1.05.12".
|
||||
** \return Library version number as a null-terminated string.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT char const * BltVersionGetString(void)
|
||||
{
|
||||
return BLT_VERSION_STRING;
|
||||
} /*** end of BltVersionGetString ***/
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* S E S S I O N / T R A N S P O R T L A Y E R S
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the firmware update session for a specific communication
|
||||
** protocol and transport layer. This function is typically called once at
|
||||
** the start of the firmware update.
|
||||
** \param sessionType The communication protocol to use for this session. It should
|
||||
** be a BLT_SESSION_xxx value.
|
||||
** \param sessionSettings Pointer to a structure with communication protocol specific
|
||||
** settings.
|
||||
** \param transportType The transport layer to use for the specified communication
|
||||
** protocol. It should be a BLT_TRANSPORT_xxx value.
|
||||
** \param transportSettings Pointer to a structure with transport layer specific
|
||||
** settings.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType,
|
||||
void const * sessionSettings,
|
||||
uint32_t transportType,
|
||||
void const * transportSettings)
|
||||
{
|
||||
/* Check parameters. Note that the settings-pointers are allowed to be NULL in case
|
||||
* no additional settings are needed for the specified session or transport type.
|
||||
*/
|
||||
assert(sessionType == BLT_SESSION_XCP_V10);
|
||||
assert( (transportType == BLT_TRANSPORT_XCP_V10_RS232) || \
|
||||
(transportType == BLT_TRANSPORT_XCP_V10_CAN) );
|
||||
|
||||
/* Initialize the correct session. */
|
||||
if (sessionType == BLT_SESSION_XCP_V10) /*lint !e774 */
|
||||
{
|
||||
/* Verify settingsSettings parameter because the XCP loader requires them. */
|
||||
assert(sessionSettings != NULL);
|
||||
/* Only continue if the settingsSettings parameter is valid. */
|
||||
if (sessionSettings != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Cast session settings to the correct type. */
|
||||
tBltSessionSettingsXcpV10 * bltSessionSettingsXcpV10Ptr;
|
||||
bltSessionSettingsXcpV10Ptr = ((tBltSessionSettingsXcpV10 *)sessionSettings);
|
||||
/* Convert session settings to the format supported by the XCP loader module. */
|
||||
tXcpLoaderSettings xcpLoaderSettings;
|
||||
xcpLoaderSettings.timeoutT1 = bltSessionSettingsXcpV10Ptr->timeoutT1;
|
||||
xcpLoaderSettings.timeoutT3 = bltSessionSettingsXcpV10Ptr->timeoutT3;
|
||||
xcpLoaderSettings.timeoutT4 = bltSessionSettingsXcpV10Ptr->timeoutT4;
|
||||
xcpLoaderSettings.timeoutT5 = bltSessionSettingsXcpV10Ptr->timeoutT5;
|
||||
xcpLoaderSettings.timeoutT7 = bltSessionSettingsXcpV10Ptr->timeoutT7;
|
||||
xcpLoaderSettings.transport = NULL;
|
||||
xcpLoaderSettings.transportSettings = NULL;
|
||||
/* Link the correct transport layer. */
|
||||
if (transportType == BLT_TRANSPORT_XCP_V10_RS232)
|
||||
{
|
||||
/* Verify transportSettings parameters because the XCP UART transport layer
|
||||
* requires them.
|
||||
*/
|
||||
assert(transportSettings != NULL);
|
||||
/* Only continue if the transportSettings parameter is valid. */
|
||||
if (transportSettings != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Cast transport settings to the correct type. */
|
||||
tBltTransportSettingsXcpV10Rs232 * bltTransportSettingsXcpV10Rs232Ptr;
|
||||
bltTransportSettingsXcpV10Rs232Ptr =
|
||||
(tBltTransportSettingsXcpV10Rs232 * )transportSettings;
|
||||
/* Convert transport settings to the format supported by the XCP UART transport
|
||||
* layer. It was made static to make sure it doesn't get out of scope when
|
||||
* used in xcpLoaderSettings.
|
||||
*/
|
||||
static tXcpTpUartSettings xcpTpUartSettings;
|
||||
xcpTpUartSettings.baudrate = bltTransportSettingsXcpV10Rs232Ptr->baudrate;
|
||||
xcpTpUartSettings.portname = bltTransportSettingsXcpV10Rs232Ptr->portName;
|
||||
/* Store transport layer settings in the XCP loader settings. */
|
||||
xcpLoaderSettings.transportSettings = &xcpTpUartSettings;
|
||||
/* Link the transport layer to the XCP loader settings. */
|
||||
xcpLoaderSettings.transport = XcpTpUartGetTransport();
|
||||
}
|
||||
}
|
||||
/* Perform actual session initialization. */
|
||||
SessionInit(XcpLoaderGetProtocol(), &xcpLoaderSettings);
|
||||
}
|
||||
}
|
||||
} /*** end of BltSessionInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the firmware update session. This function is typically called
|
||||
** once at the end of the firmware update.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltSessionTerminate(void)
|
||||
{
|
||||
/* Terminate the session. */
|
||||
SessionTerminate();
|
||||
} /*** end of BltSessionTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Starts the firmware update session. This is were the library attempts to
|
||||
** activate and connect with the bootloader running on the target, through
|
||||
** the transport layer that was specified during the session's initialization.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionStart(void)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Start the session. */
|
||||
if (SessionStart())
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltSessionStart ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Stops the firmware update session. This is there the library disconnects
|
||||
** the transport layer as well.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltSessionStop(void)
|
||||
{
|
||||
/* Stop the session. */
|
||||
SessionStop();
|
||||
} /*** end of BltSessionStop ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Requests the target to erase the specified range of memory on the target.
|
||||
** Note that the target automatically aligns this to the erasable memory
|
||||
** block sizes. This typically results in more memory being erased that the
|
||||
** range that was specified here. Refer to the target implementation for
|
||||
** details.
|
||||
** \param address The starting memory address for the erase operation.
|
||||
** \param len The total number of bytes to erase from memory.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionClearMemory(uint32_t address, uint32_t len)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if (len > 0)
|
||||
{
|
||||
/* Pass the request on to the session module. */
|
||||
if (SessionClearMemory(address, len))
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltSessionClearMemory ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Requests the target to program the specified data to memory. Note that it
|
||||
** is the responsibility of the application to make sure the memory range was
|
||||
** erased beforehand.
|
||||
** \param address The starting memory address for the write operation.
|
||||
** \param len The number of bytes in the data buffer that should be written.
|
||||
** \param data Pointer to the byte array with data to write.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionWriteData(uint32_t address, uint32_t len,
|
||||
uint8_t const * data)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the session module. */
|
||||
if (SessionWriteData(address, len, data))
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltSessionWriteData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Requests the target to upload the specified range from memory and store its
|
||||
** contents in the specified data buffer.
|
||||
** \param address The starting memory address for the read operation.
|
||||
** \param len The number of bytes to upload from the target and store in the data
|
||||
** buffer.
|
||||
** \param data Pointer to the byte array where the uploaded data should be stored.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionReadData(uint32_t address, uint32_t len,
|
||||
uint8_t * data)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the session module. */
|
||||
if (SessionReadData(address, len, data))
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltSessionReadData ***/
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* F I R M W A R E D A T A
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the firmware data module for a specified firmware file parser.
|
||||
** \param parserType The firmware file parser to use in this module. It should be a
|
||||
** BLT_FIRMWARE_PARSER_xxx value.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltFirmwareInit(uint32_t parserType)
|
||||
{
|
||||
tFirmwareParser const * firmwareParser = NULL;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(parserType == BLT_FIRMWARE_PARSER_SRECORD);
|
||||
|
||||
/* Set the parser pointer. */
|
||||
if (parserType == BLT_FIRMWARE_PARSER_SRECORD) /*lint !e774 */
|
||||
{
|
||||
firmwareParser = SRecParserGetParser();
|
||||
}
|
||||
/* Initialize the firmware data module by linking the firmware file parser. */
|
||||
FirmwareInit(firmwareParser);
|
||||
} /*** end of BltFirmwareInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the firmware data module. Typically called at the end of the
|
||||
** program when the firmware data module is no longer needed.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltFirmwareTerminate(void)
|
||||
{
|
||||
/* Terminate the firmware data module. */
|
||||
FirmwareTerminate();
|
||||
} /*** end of BltFirmwareTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Loads firmware data from the specified file using the firmware file parser
|
||||
** that was specified during the initialization of this module.
|
||||
** \param firmwareFile Filename of the firmware file to load.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareLoadFromFile(char const * firmwareFile)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(firmwareFile != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (firmwareFile != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the firmware data module. */
|
||||
if (FirmwareLoadFromFile(firmwareFile))
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltFirmwareLoadFromFile ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Writes firmware data to the specified file using the firmware file parser
|
||||
** that was specified during the initialization of this module.
|
||||
** \param firmwareFile Filename of the firmware file to write to.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareSaveToFile(char const * firmwareFile)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(firmwareFile != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (firmwareFile != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the firmware data module. */
|
||||
if (FirmwareSaveToFile(firmwareFile))
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltFirmwareSaveToFile ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains the number of firmware data segments that are currently present
|
||||
** in the firmware data module.
|
||||
** \return The total number of segments.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareGetSegmentCount(void)
|
||||
{
|
||||
/* Pass the request on to the firmware data module. */
|
||||
return FirmwareGetSegmentCount();
|
||||
} /*** end of BltFirmwareGetSegmentCount ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains the contents of the firmware data segment that was specified by the
|
||||
** index parameter.
|
||||
** \param idx The segment index. It should be a value greater or equal to zero and
|
||||
** smaller than the value returned by \ref BltFirmwareGetSegmentCount.
|
||||
** \param address Pointer to where the segment's base address will be written to.
|
||||
** \param len Pointer to where the segment's length will be written to.
|
||||
** \return Pointer to the segment data if successful, NULL otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint8_t * BltFirmwareGetSegment(uint32_t idx, uint32_t * address,
|
||||
uint32_t * len)
|
||||
{
|
||||
uint8_t * result = NULL;
|
||||
tFirmwareSegment *segmentPtr;
|
||||
|
||||
/* Verify parameters. Note that it is okay for the data parameter to be NULL. */
|
||||
assert(idx < FirmwareGetSegmentCount());
|
||||
assert(address != NULL);
|
||||
assert(len != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ((address != NULL) && (len != NULL) &&
|
||||
(idx < FirmwareGetSegmentCount()) ) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the firmware data module. */
|
||||
segmentPtr = FirmwareGetSegment(idx);
|
||||
/* Process the result. */
|
||||
if (segmentPtr != NULL)
|
||||
{
|
||||
*address = segmentPtr->base;
|
||||
*len = segmentPtr->length;
|
||||
result = segmentPtr->data;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltFirmwareGetSegment ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Adds data to the segments that are currently present in the firmware data
|
||||
** module. If the data overlaps with already existing data, the existing data
|
||||
** gets overwritten. The size of a segment is automatically adjusted or a new
|
||||
** segment gets created, if necessary.
|
||||
** \param address Base address of the firmware data.
|
||||
** \param len Number of bytes to add.
|
||||
** \param data Pointer to array with data bytes that should be added.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareAddData(uint32_t address, uint32_t len,
|
||||
uint8_t const * data)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(len > 0);
|
||||
assert(data != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ( (len > 0) && (data != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the firmware data module. */
|
||||
if (FirmwareAddData(address, len, data))
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltFirmwareAddData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Removes data from the segments that are currently present in the firmware
|
||||
** data module. The size of a segment is automatically adjusted or removed, if
|
||||
** necessary.
|
||||
** \param address Base address of the firmware data.
|
||||
** \param len Number of bytes to remove.
|
||||
** \return BLT_RESULT_OK if successful, BLT_RESULT_ERROR_xxx otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareRemoveData(uint32_t address, uint32_t len)
|
||||
{
|
||||
uint32_t result = BLT_RESULT_ERROR_GENERIC;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (len > 0)
|
||||
{
|
||||
/* Pass the request on to the firmware data module. */
|
||||
if (FirmwareRemoveData(address, len))
|
||||
{
|
||||
result = BLT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltFirmwareRemoveData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Clears all data and segments that are currently present in the firmware
|
||||
** data module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltFirmwareClearData(void)
|
||||
{
|
||||
/* Pass the request on to the firmware data module. */
|
||||
FirmwareClearData();
|
||||
} /*** end of BltFirmwareClearData ***/
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* G E N E R I C U T I L I T I E S
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
** \brief Calculates a 16-bit CRC value over the specified data.
|
||||
** \param data Array with bytes over which the CRC16 should be calculated.
|
||||
** \param len Number of bytes in the data array.
|
||||
** \return The 16-bit CRC value.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint16_t BltUtilCrc16Calculate(uint8_t const * data, uint32_t len)
|
||||
{
|
||||
uint16_t result = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Perform checksum calculation. */
|
||||
result = UtilChecksumCrc16Calculate(data, len);
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltUtilCrc16Calculate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Calculates a 32-bit CRC value over the specified data.
|
||||
** \param data Array with bytes over which the CRC32 should be calculated.
|
||||
** \param len Number of bytes in the data array.
|
||||
** \return The 32-bit CRC value.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltUtilCrc32Calculate(uint8_t const * data, uint32_t len)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Perform checksum calculation. */
|
||||
result = UtilChecksumCrc32Calculate(data, len);
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltUtilCrc32Calculate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Get the system time in milliseconds.
|
||||
** \return Time in milliseconds.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltUtilTimeGetSystemTime(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
/* Pass the request on to the utility module. */
|
||||
result = UtilTimeGetSystemTimeMs();
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of BltUtilTimeGetSystemTime ***/
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Performs a delay of the specified amount of milliseconds.
|
||||
** \param delay Delay time in milliseconds.
|
||||
**
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltUtilTimeDelayMs(uint16_t delay)
|
||||
{
|
||||
/* Pass the request on to the utility module. */
|
||||
UtilTimeDelayMs(delay);
|
||||
} /*** end of BltUtilTimeDelayMs ***/
|
||||
|
||||
|
||||
/*********************************** end of openblt.c **********************************/
|
||||
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
/************************************************************************************//**
|
||||
* \file openblt.h
|
||||
* \brief OpenBLT host library header file.
|
||||
* \ingroup Library
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
* \defgroup Library Library API
|
||||
* \brief OpenBLT Library API.
|
||||
* \details
|
||||
* The Library API contains the application programming interface for the OpenBLT libary.
|
||||
* it defines the functions and definitions that an external program uses to access the
|
||||
* library's functionality.
|
||||
****************************************************************************************/
|
||||
#ifndef OPENBLT_H
|
||||
#define OPENBLT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/* CMake automatically defines macro openblt_shared_EXPORTS when building the shared
|
||||
* version of the library. When building under windows, this is used to set the export
|
||||
* macro, which is needed to confige the library functions.
|
||||
*/
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(openblt_shared_EXPORTS)
|
||||
#define LIBOPENBLT_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIBOPENBLT_EXPORT
|
||||
#endif /* openblt_shared_EXPORTS */
|
||||
#else /* defined(_WIN32) || defined(_WIN64) */
|
||||
#define LIBOPENBLT_EXPORT
|
||||
#endif
|
||||
|
||||
/** \brief Function return value for when everything went okay. */
|
||||
#define BLT_RESULT_OK (0u)
|
||||
|
||||
/** \brief Function return value for when a generic error occured. */
|
||||
#define BLT_RESULT_ERROR_GENERIC (1u)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* V E R S I O N I N F O R M A T I O N
|
||||
****************************************************************************************/
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint32_t BltVersionGetNumber(void);
|
||||
LIBOPENBLT_EXPORT char const * BltVersionGetString(void);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* S E S S I O N / T R A N S P O R T L A Y E R S
|
||||
****************************************************************************************/
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/** \brief XCP protocol version 1.0. XCP is a universal measurement and calibration
|
||||
* communication protocol. It contains functionality for reading, programming,
|
||||
* and erasing (non-volatile) memory making it a good fit for bootloader
|
||||
* purposes.
|
||||
*/
|
||||
#define BLT_SESSION_XCP_V10 ((uint32_t)0u)
|
||||
|
||||
/** \brief Transport layer for the XCP v1.0 protocol that uses RS-232 serial
|
||||
* communication for data exchange.
|
||||
*/
|
||||
#define BLT_TRANSPORT_XCP_V10_RS232 ((uint32_t)0u)
|
||||
|
||||
/** \brief Transport layer for the XCP v1.0 protocol that uses Controller Area Network
|
||||
* (CAN) for data exchange.
|
||||
*/
|
||||
#define BLT_TRANSPORT_XCP_V10_CAN ((uint32_t)1u)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Structure layout of the XCP version 1.0 session settings. */
|
||||
typedef struct t_blt_session_settings_xcp_v10
|
||||
{
|
||||
uint16_t timeoutT1; /**< Command response timeout in milliseconds. */
|
||||
uint16_t timeoutT3; /**< Start programming timeout in milliseconds. */
|
||||
uint16_t timeoutT4; /**< Erase memory timeout in milliseonds. */
|
||||
uint16_t timeoutT5; /**< Program memory and reset timeout in milliseonds. */
|
||||
uint16_t timeoutT7; /**< Busy wait timer timeout in milliseonds. */
|
||||
char const * seedKeyFile; /**< Seed/key algorithm library filename. */
|
||||
} tBltSessionSettingsXcpV10;
|
||||
|
||||
/** \brief Structure layout of the XCP version 1.0 RS232 transport layer settings. The
|
||||
* portName field is platform dependent. On Linux based systems this should be
|
||||
* the filename of the tty-device, such as "/dev/tty0". On Windows based systems
|
||||
* it should be the name of the COM-port, such as "COM1".
|
||||
*/
|
||||
typedef struct t_blt_transport_settings_xcp_v10_rs232
|
||||
{
|
||||
char const * portName; /**< Communication port name such as /dev/tty0. */
|
||||
uint32_t baudrate; /**< Communication speed in bits/sec. */
|
||||
} tBltTransportSettingsXcpV10Rs232;
|
||||
|
||||
/** \brief Structure layout of the XCP version 1.0 CAN transport layer settings. The
|
||||
* deviceName field is platform dependent. On Linux based systems this should be
|
||||
* the socketCAN interface name such as "can0". The terminal command "ip addr"
|
||||
* can be issued to view a list of interfaces that are up and available. Under
|
||||
* Linux it is assumed that the socketCAN interface is already configured on the
|
||||
* system, before using the OpenBLT library. When baudrate is configured when
|
||||
* bringing up the system, so the baudrate field in this structure is don't care
|
||||
* when using the library on a Linux was system.
|
||||
* On Windows based systems, the device name is a name that is pre-defined by
|
||||
* this library for the supported CAN adapters. The device name should be one of
|
||||
* the following: "peak_pcanusb", "kvaser_leaflight", or "lawicel_canusb".
|
||||
* Field use extended is a boolean field. When set to 0, the specified transmitId
|
||||
* and receiveId are assumed to be 11-bit standard CAN identifier. It the field
|
||||
* is 1, these identifiers are assumed to be 29-bit extended CAN identifiers.
|
||||
*/
|
||||
typedef struct t_blt_transport_settings_xcp_v10_can
|
||||
{
|
||||
char const * deviceName; /**< Device name such as can0. */
|
||||
uint32_t deviceChannel; /**< Channel on the device to use. */
|
||||
uint32_t baudrate; /**< Communication speed in bits/sec. */
|
||||
uint32_t transmitId; /**< Transmit CAN identifier. */
|
||||
uint32_t receiveId; /**< Receive CAN identifier. */
|
||||
uint32_t useExtended; /**< Boolean to configure 29-bit CAN identifiers. */
|
||||
} tBltTransportSettingsXcpV10Can;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType,
|
||||
void const * sessionSettings,
|
||||
uint32_t transportType,
|
||||
void const * transportSettings);
|
||||
LIBOPENBLT_EXPORT void BltSessionTerminate(void);
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionStart(void);
|
||||
LIBOPENBLT_EXPORT void BltSessionStop(void);
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionClearMemory(uint32_t address, uint32_t len);
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionWriteData(uint32_t address, uint32_t len,
|
||||
uint8_t const * data);
|
||||
LIBOPENBLT_EXPORT uint32_t BltSessionReadData(uint32_t address, uint32_t len,
|
||||
uint8_t * data);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* F I R M W A R E D A T A
|
||||
****************************************************************************************/
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/** \brief The S-record parser enables writing and reading firmware data to and from
|
||||
* file formatted as Motorola S-record. This is a widely known file format and
|
||||
* pretty much all microcontroller compiler toolchains included functionality to
|
||||
* output or convert the firmware's data as an S-record.
|
||||
*/
|
||||
#define BLT_FIRMWARE_PARSER_SRECORD ((uint32_t)0u)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT void BltFirmwareInit(uint32_t parserType);
|
||||
LIBOPENBLT_EXPORT void BltFirmwareTerminate(void);
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareLoadFromFile(char const * firmwareFile);
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareSaveToFile(char const * firmwareFile);
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareGetSegmentCount(void);
|
||||
LIBOPENBLT_EXPORT uint8_t * BltFirmwareGetSegment(uint32_t idx, uint32_t * address,
|
||||
uint32_t * len);
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareAddData(uint32_t address, uint32_t len,
|
||||
uint8_t const * data);
|
||||
LIBOPENBLT_EXPORT uint32_t BltFirmwareRemoveData(uint32_t address, uint32_t len);
|
||||
LIBOPENBLT_EXPORT void BltFirmwareClearData(void);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* G E N E R I C U T I L I T I E S
|
||||
****************************************************************************************/
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
LIBOPENBLT_EXPORT uint16_t BltUtilCrc16Calculate(uint8_t const * data, uint32_t len);
|
||||
LIBOPENBLT_EXPORT uint32_t BltUtilCrc32Calculate(uint8_t const * data, uint32_t len);
|
||||
LIBOPENBLT_EXPORT uint32_t BltUtilTimeGetSystemTime(void);
|
||||
LIBOPENBLT_EXPORT void BltUtilTimeDelayMs(uint16_t delay);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPENBLT_H */
|
||||
/********************************* end of openblt.h ************************************/
|
||||
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
unit OpenBlt;
|
||||
//***************************************************************************************
|
||||
// Description: Unit for accessing the OpenBLT shared library.
|
||||
// File Name: openblt.pas
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
// C O P Y R I G H T
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
//
|
||||
// This software has been carefully tested, but is not guaranteed for any particular
|
||||
// purpose. The author does not offer any warranties and does not guarantee the accuracy,
|
||||
// adequacy, or completeness of the software and is not responsible for any errors or
|
||||
// omissions or the results obtained from use of the software.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
// L I C E N S E
|
||||
//---------------------------------------------------------------------------------------
|
||||
// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the GNU General Public License for more details.
|
||||
//
|
||||
// You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
// should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
//
|
||||
//***************************************************************************************
|
||||
{$IFDEF FPC}
|
||||
{$MODE objfpc}{$H+}
|
||||
{$ENDIF}
|
||||
|
||||
interface
|
||||
//***************************************************************************************
|
||||
// Global Includes
|
||||
//***************************************************************************************
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
//***************************************************************************************
|
||||
// Global Constant Declarations
|
||||
//***************************************************************************************
|
||||
const
|
||||
// Name of the external library.
|
||||
LIBOPENBLT_LIBNAME = 'libopenblt';
|
||||
// Function return value for when everything went okay.
|
||||
BLT_RESULT_OK = 0;
|
||||
// Function return value for when a generic error occured.
|
||||
BLT_RESULT_ERROR_GENERIC = 1;
|
||||
|
||||
|
||||
//***************************************************************************************
|
||||
// V E R S I O N I N F O R M A T I O N
|
||||
//***************************************************************************************
|
||||
function BltVersionGetNumber: LongWord; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltVersionGetString: PAnsiChar; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
|
||||
|
||||
//***************************************************************************************
|
||||
// S E S S I O N / T R A N S P O R T L A Y E R S
|
||||
//***************************************************************************************
|
||||
const
|
||||
// XCP protocol version 1.0. XCP is a universal measurement and calibration communica-
|
||||
// tion protocol. It contains functionality for reading, programming, and erasing
|
||||
// (non-volatile) memory making it a good fit for bootloader purposes.
|
||||
BLT_SESSION_XCP_V10: LongWord = 0;
|
||||
// Transport layer for the XCP v1.0 protocol that uses RS-232 serial communication for
|
||||
// data exchange.
|
||||
BLT_TRANSPORT_XCP_V10_RS232: LongWord = 0;
|
||||
// Transport layer for the XCP v1.0 protocol that uses Controller Area Network (CAN)
|
||||
// for data exchange.
|
||||
BLT_TRANSPORT_XCP_V10_CAN: LongWord = 1;
|
||||
|
||||
type
|
||||
// Structure layout of the XCP version 1.0 session settings.
|
||||
tBltSessionSettingsXcpV10 = record
|
||||
timeoutT1: Word; // Command response timeout in milliseconds.
|
||||
timeoutT3: Word; // Start programming timeout in milliseconds.
|
||||
timeoutT4: Word; // Erase memory timeout in milliseonds.
|
||||
timeoutT5: Word; // Program memory and reset timeout in milliseonds.
|
||||
timeoutT7: Word; // Busy wait timer timeout in milliseonds.
|
||||
seedKeyFile: PAnsiChar; // Seed/key algorithm library filename.
|
||||
end;
|
||||
|
||||
// Structure layout of the XCP version 1.0 RS232 transport layer settings.
|
||||
tBltTransportSettingsXcpV10Rs232 = record
|
||||
portName: PAnsiChar; // Communication port name such as /dev/tty0.
|
||||
baudrate: LongWord; // Communication speed in bits/sec.
|
||||
end;
|
||||
|
||||
// Structure layout of the XCP version 1.0 CAN transport layer settings.
|
||||
tBltTransportSettingsXcpV10Can = record
|
||||
deviceName: PAnsiChar; // Device name such as /dev/can0.
|
||||
deviceChannel: LongWord; // Channel on the device to use.
|
||||
baudrate: LongWord; // Communication speed in bits/sec.
|
||||
transmitId: LongWord; // Transmit CAN identifier.
|
||||
receiveId: LongWord; // Receive CAN identifier.
|
||||
useExtended: LongWord; // Boolean to configure 29-bit CAN identifiers.
|
||||
end;
|
||||
|
||||
procedure BltSessionInit(sessionType: LongWord;
|
||||
sessionSettings: Pointer;
|
||||
transportType: LongWord;
|
||||
transportSettings: Pointer);
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
procedure BltSessionTerminate; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltSessionStart: LongWord; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
procedure BltSessionStop; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltSessionClearMemory(address: LongWord;
|
||||
len: LongWord): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltSessionWriteData(address: LongWord;
|
||||
len: LongWord;
|
||||
data: PByte): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltSessionReadData(address: LongWord;
|
||||
len: LongWord;
|
||||
data: PByte): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
|
||||
|
||||
//***************************************************************************************
|
||||
// F I R M W A R E D A T A C O N T R O L
|
||||
//***************************************************************************************
|
||||
const
|
||||
// The S-record parser enables writing and reading firmware data to and from file
|
||||
// formatted as Motorola S-record. This is a widely known file format and pretty much
|
||||
// all microcontroller compiler toolchains included functionality to output or convert
|
||||
// the firmware's data as an S-record.
|
||||
BLT_FIRMWARE_PARSER_SRECORD: LongWord = 0;
|
||||
|
||||
procedure BltFirmwareInit(parserType: LongWord); cdecl; external LIBOPENBLT_LIBNAME;
|
||||
procedure BltFirmwareTerminate; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltFirmwareLoadFromFile(firmwareFile: PAnsiChar): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltFirmwareSaveToFile(firmwareFile: PAnsiChar): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltFirmwareGetSegmentCount: LongWord; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltFirmwareGetSegment(idx: LongWord;
|
||||
var address: LongWord;
|
||||
var len: LongWord): PByte;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltFirmwareAddData(address: LongWord;
|
||||
len: LongWord;
|
||||
data: PByte): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltFirmwareRemoveData(address: LongWord;
|
||||
len: LongWord): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
procedure BltFirmwareClearData; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
|
||||
|
||||
//***************************************************************************************
|
||||
// G E N E R I C U T I L I T I E S
|
||||
//***************************************************************************************
|
||||
function BltUtilCrc16Calculate(data: PByte; len: LongWord): Word;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltUtilCrc32Calculate(data: PByte; len: LongWord): LongWord;
|
||||
cdecl; external LIBOPENBLT_LIBNAME;
|
||||
function BltUtilTimeGetSystemTime: LongWord; cdecl; external LIBOPENBLT_LIBNAME;
|
||||
procedure BltUtilTimeDelayMs(delay: Word); cdecl; external LIBOPENBLT_LIBNAME;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
end.
|
||||
//******************************** end of openblt.pas ***********************************
|
||||
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/linux/serialport.c
|
||||
* \brief Serial port source file.
|
||||
* \ingroup Session
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <unistd.h> /* UNIX standard functions */
|
||||
#include <termios.h> /* POSIX terminal control */
|
||||
#include <fcntl.h> /* file control definitions */
|
||||
#include <sys/ioctl.h> /* system I/O control */
|
||||
#include "serialport.h" /* serial port module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Invalid serial port device handle. */
|
||||
#define SERIALPORT_INVALID_HANDLE (-1)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Serial port handle. */
|
||||
static int32_t portHandle;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local constant declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Lookup table for converting this module's generic baudrate value to a value
|
||||
* supported by the low level interface.
|
||||
*/
|
||||
static const speed_t baudrateLookup[] =
|
||||
{
|
||||
B9600, /**< Index 0 = SERIALPORT_BR9600 */
|
||||
B19200, /**< Index 1 = SERIALPORT_BR19200 */
|
||||
B38400, /**< Index 2 = SERIALPORT_BR38400 */
|
||||
B57600, /**< Index 3 = SERIALPORT_BR57600 */
|
||||
B115200 /**< Index 4 = SERIALPORT_BR115200 */
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the serial port module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SerialPortInit(void)
|
||||
{
|
||||
/* Invalidate the port handle. */
|
||||
portHandle = SERIALPORT_INVALID_HANDLE;
|
||||
} /*** end of SerialPortInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the serial port module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SerialPortTerminate(void)
|
||||
{
|
||||
/* Make sure the serial port is closed. */
|
||||
SerialPortClose();
|
||||
} /*** end of SerialPortTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Opens the connection with the serial port configured as 8,N,1 and no flow
|
||||
** control.
|
||||
** \param portname The name of the serial port to open, i.e. /dev/ttyUSB0.
|
||||
** \param baudrate The desired communication speed.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SerialPortOpen(char const * portname, tSerialPortBaudrate baudrate)
|
||||
{
|
||||
bool result = false;
|
||||
struct termios options = { 0 };
|
||||
int32_t iFlags;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(portname != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if (portname != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Assume the result to be okay from here on and only set it to error when a problem
|
||||
* was detected.
|
||||
*/
|
||||
result = true;
|
||||
/* Open the port. */
|
||||
portHandle = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
/* Check the result */
|
||||
if (portHandle == SERIALPORT_INVALID_HANDLE)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
/* Configure the device to block during read operations. */
|
||||
if (result)
|
||||
{
|
||||
if (fcntl(portHandle, F_SETFL, 0) == -1)
|
||||
{
|
||||
SerialPortClose();
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Get the current options for the port. */
|
||||
if (result)
|
||||
{
|
||||
if (tcgetattr(portHandle, &options) == -1)
|
||||
{
|
||||
SerialPortClose();
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Configure the baudrate. */
|
||||
if (result)
|
||||
{
|
||||
if (cfsetispeed(&options, baudrateLookup[baudrate]) == -1)
|
||||
{
|
||||
SerialPortClose();
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
if (cfsetospeed(&options, baudrateLookup[baudrate]) == -1)
|
||||
{
|
||||
SerialPortClose();
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
/* Input modes - clear indicated ones giving: no break, no CR to NL,
|
||||
* no parity check, no strip char, no start/stop output (sic) control.
|
||||
*/
|
||||
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
/* Output modes - clear giving: no post processing such as NL to CR+NL. */
|
||||
options.c_oflag &= ~(OPOST);
|
||||
/* Control modes - set 8 bit chars */
|
||||
options.c_cflag |= (CS8);
|
||||
/* Local modes - clear giving: echoing off, canonical off (no erase with
|
||||
* backspace, ^U,...), no extended functions, no signal chars (^Z,^C).
|
||||
*/
|
||||
options.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
||||
/* Configure timeouts. */
|
||||
options.c_cc[VMIN] = 0;
|
||||
options.c_cc[VTIME] = 1; /* in units of 1/10th of a second */
|
||||
/* Set the new options for the port. */
|
||||
if (tcsetattr(portHandle, TCSAFLUSH, &options) == -1)
|
||||
{
|
||||
SerialPortClose();
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Turn on DTR. */
|
||||
if (result)
|
||||
{
|
||||
iFlags = TIOCM_DTR;
|
||||
if (ioctl(portHandle, TIOCMBIS, &iFlags) == -1)
|
||||
{
|
||||
SerialPortClose();
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SerialPortOpen ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Closes the connection with the serial port.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SerialPortClose(void)
|
||||
{
|
||||
/* Close the port handle if valid. */
|
||||
if (portHandle != SERIALPORT_INVALID_HANDLE)
|
||||
{
|
||||
close(portHandle);
|
||||
}
|
||||
/* Invalidate handle. */
|
||||
portHandle = SERIALPORT_INVALID_HANDLE;
|
||||
} /*** end of SerialPortClose ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Writes data to the serial port.
|
||||
** \param data Pointer to byte array with data to write.
|
||||
** \param length Number of bytes to write.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SerialPortWrite(uint8_t const * data, uint32_t length)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(length > 0);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if ( (data != NULL) && (length > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Submit the data for sending. */
|
||||
if ((uint32_t)write(portHandle, data, length) == length)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SerialPortWrite ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Reads data from the serial port in a blocking manner.
|
||||
** \param data Pointer to byte array to store read data.
|
||||
** \param length Number of bytes to read.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SerialPortRead(uint8_t * data, uint32_t length)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(length > 0);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if ( (data != NULL) && (length > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Attempt to read the requested data. */
|
||||
if ((uint32_t)read(portHandle, data, length) == length)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SerialPortRead ***/
|
||||
|
||||
|
||||
/*********************************** end of serialport.c *******************************/
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/linux/timeutil.c
|
||||
* \brief Time utility source file.
|
||||
* \ingroup Utility
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <unistd.h> /* UNIX standard functions */
|
||||
#include <sys/time.h> /* time definitions */
|
||||
#include "util.h" /* Utility module */
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Get the system time in milliseconds.
|
||||
** \return Time in milliseconds.
|
||||
**
|
||||
****************************************************************************************/
|
||||
uint32_t UtilTimeGetSystemTimeMs(void)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
struct timeval tv;
|
||||
|
||||
if (gettimeofday(&tv, NULL) == 0)
|
||||
{
|
||||
result = (((uint32_t)tv.tv_sec * 1000ul) + ((uint32_t)tv.tv_usec / 1000ul));
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of UtilTimeGetSystemTimeMs ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Performs a delay of the specified amount of milliseconds.
|
||||
** \param delay Delay time in milliseconds.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilTimeDelayMs(uint16_t delay)
|
||||
{
|
||||
(void)usleep(1000u * delay);
|
||||
} /*** end of UtilTimeDelayMs **/
|
||||
|
||||
|
||||
/*********************************** end of timeutil.c *********************************/
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/windows/serialport.c
|
||||
* \brief Serial port source file.
|
||||
* \ingroup Session
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <windows.h> /* for windows library */
|
||||
#include "serialport.h" /* serial port module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
#define UART_TX_BUFFER_SIZE (1024u) /**< transmission buffer size */
|
||||
#define UART_RX_BUFFER_SIZE (1024u) /**< reception buffer size */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Serial port handle. */
|
||||
static HANDLE hUart;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
static uint32_t SerialConvertBaudrate(tSerialPortBaudrate baudrate);
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the serial port module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SerialPortInit(void)
|
||||
{
|
||||
/* Invalidate the port handle. */
|
||||
hUart = INVALID_HANDLE_VALUE;
|
||||
} /*** end of SerialPortInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the serial port module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SerialPortTerminate(void)
|
||||
{
|
||||
/* Make sure the serial port is closed. */
|
||||
SerialPortClose();
|
||||
} /*** end of SerialPortTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Opens the connection with the serial port configured as 8,N,1 and no flow
|
||||
** control.
|
||||
** \param portname The name of the serial port to open, i.e. COM4.
|
||||
** \param baudrate The desired communication speed.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SerialPortOpen(char const * portname, tSerialPortBaudrate baudrate)
|
||||
{
|
||||
bool result = false;
|
||||
COMMTIMEOUTS timeouts = { 0 };
|
||||
DCB dcbSerialParams = { 0 };
|
||||
char portStr[64] = "\\\\.\\";
|
||||
|
||||
/* Check parameters. */
|
||||
assert(portname != NULL);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if (portname != NULL)
|
||||
{
|
||||
/* Assume the result to be okay from here on and only set it to error when a problem
|
||||
* was detected.
|
||||
*/
|
||||
result = true;
|
||||
/* Construct the COM port name as a string. */
|
||||
strcat(portStr, portname);
|
||||
|
||||
/* Obtain access to the COM port. */
|
||||
hUart = CreateFile(portStr, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, 0);
|
||||
/* Validate COM port handle. */
|
||||
if (hUart == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
/* Get current COM port configuration. */
|
||||
if (result)
|
||||
{
|
||||
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
|
||||
if (!GetCommState(hUart, &dcbSerialParams))
|
||||
{
|
||||
(void)CloseHandle(hUart);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the baudrate and 8,n,1. */
|
||||
if (result)
|
||||
{
|
||||
dcbSerialParams.BaudRate = SerialConvertBaudrate(baudrate);
|
||||
dcbSerialParams.ByteSize = 8;
|
||||
dcbSerialParams.StopBits = ONESTOPBIT;
|
||||
dcbSerialParams.Parity = NOPARITY;
|
||||
dcbSerialParams.fOutX = FALSE;
|
||||
dcbSerialParams.fInX = FALSE;
|
||||
dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
if (!SetCommState(hUart, &dcbSerialParams))
|
||||
{
|
||||
(void)CloseHandle(hUart);
|
||||
result =false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set communication timeout parameters. */
|
||||
if (result)
|
||||
{
|
||||
timeouts.ReadIntervalTimeout = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = 0;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 100;
|
||||
timeouts.WriteTotalTimeoutConstant = 0;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 100;
|
||||
if (!SetCommTimeouts(hUart, &timeouts))
|
||||
{
|
||||
(void)CloseHandle(hUart);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set transmit and receive buffer sizes. */
|
||||
if (result)
|
||||
{
|
||||
if (!SetupComm(hUart, UART_RX_BUFFER_SIZE, UART_TX_BUFFER_SIZE))
|
||||
{
|
||||
(void)CloseHandle(hUart);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Empty the transmit and receive buffers. */
|
||||
if (result)
|
||||
{
|
||||
if (!FlushFileBuffers(hUart))
|
||||
{
|
||||
(void)CloseHandle(hUart);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SerialPortOpen ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Closes the connection with the serial port.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SerialPortClose(void)
|
||||
{
|
||||
/* Close the COM port handle if valid. */
|
||||
if (hUart != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)CloseHandle(hUart);
|
||||
}
|
||||
|
||||
/* Set handles to invalid. */
|
||||
hUart = INVALID_HANDLE_VALUE;
|
||||
} /*** end of SerialPortClose ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Writes data to the serial port.
|
||||
** \param data Pointer to byte array with data to write.
|
||||
** \param length Number of bytes to write.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SerialPortWrite(uint8_t const * data, uint32_t length)
|
||||
{
|
||||
bool result = false;
|
||||
DWORD dwWritten = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(length > 0);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if ( (data != NULL) && (length > 0) )
|
||||
{
|
||||
/* Submit the data for transmission with the serial port. */
|
||||
if (WriteFile(hUart, data, length, &dwWritten, NULL))
|
||||
{
|
||||
/* Double check that all bytes were actually transmitted. */
|
||||
if (dwWritten == length)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SerialPortWrite ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Reads data from the serial port in a blocking manner.
|
||||
** \param data Pointer to byte array to store read data.
|
||||
** \param length Number of bytes to read.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SerialPortRead(uint8_t * data, uint32_t length)
|
||||
{
|
||||
bool result = false;
|
||||
DWORD dwRead = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(length > 0);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if ( (data != NULL) && (length > 0) )
|
||||
{
|
||||
/* Attempt to read data from the serial port. */
|
||||
if (ReadFile(hUart, data, length, &dwRead, NULL))
|
||||
{
|
||||
/* Double check that all bytes were actually read. */
|
||||
if (dwRead == length)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SerialPortRead ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Opens the connection with the serial port configured as 8,N,1 and no flow
|
||||
** control.
|
||||
** \param baudrate The desired communication speed.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static uint32_t SerialConvertBaudrate(tSerialPortBaudrate baudrate)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
switch (baudrate)
|
||||
{
|
||||
case SERIALPORT_BR9600:
|
||||
result = CBR_9600;
|
||||
break;
|
||||
case SERIALPORT_BR19200:
|
||||
result = CBR_19200;
|
||||
break;
|
||||
case SERIALPORT_BR38400:
|
||||
result = CBR_38400;
|
||||
break;
|
||||
case SERIALPORT_BR57600:
|
||||
result = CBR_57600;
|
||||
break;
|
||||
case SERIALPORT_BR115200:
|
||||
result = CBR_115200;
|
||||
break;
|
||||
default:
|
||||
result = CBR_9600;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} /*** end of SerialConvertBaudrate ***/
|
||||
|
||||
|
||||
/*********************************** end of serialport.c *******************************/
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/windows/timeutil.c
|
||||
* \brief Time utility source file.
|
||||
* \ingroup Utility
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <windows.h> /* for windows library */
|
||||
#include "util.h" /* Utility module */
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Get the system time in milliseconds.
|
||||
** \return Time in milliseconds.
|
||||
**
|
||||
****************************************************************************************/
|
||||
uint32_t UtilTimeGetSystemTimeMs(void)
|
||||
{
|
||||
return GetTickCount();
|
||||
} /*** end of UtilTimeGetSystemTimeMs ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Performs a delay of the specified amount of milliseconds.
|
||||
** \param delay Delay time in milliseconds.
|
||||
** \return none.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilTimeDelayMs(uint16_t delay)
|
||||
{
|
||||
Sleep(delay);
|
||||
} /*** end of UtilTimeDelayMs **/
|
||||
|
||||
|
||||
/*********************************** end of timeutil.c *********************************/
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
\mainpage OpenBLT Host Library (LibOpenBLT)
|
||||
\details
|
||||
\tableofcontents
|
||||
\section into Introduction
|
||||
LibOpenBLT is a host library for the OpenBLT bootloader. Its purpose is to allow quick and
|
||||
easy creation of programs that can connect to and perform firmware updates on a
|
||||
microcontroller that runs the OpenBLT bootloader.
|
||||
|
||||
LibOpenBLT is written in the C programming language (C99) and is cross-platform. It has
|
||||
been successfully tested on a Windows PC, Linux PC and even embedded Linux systems such
|
||||
as a Raspberry Pi and a Beagle Board.
|
||||
|
||||
\image html libopenblt_architecture.png
|
||||
\image latex libopenblt_architecture.png
|
||||
|
||||
Both the MicroBoot (GUI) and BootCommander (CLI) firmware updater tools, which are part
|
||||
of the OpenBLT bootloader package, make use of the OpenBLT Host Library. The source code
|
||||
of these two tools serve as an additional reference on how to use the OpenBLT Host
|
||||
Library when your are developing your own custom tool.
|
||||
|
||||
Refer to the OpenBLT website for additional information regarding the OpenBLT Host
|
||||
Library, including step-by-step instructions on how to build both that shared and static
|
||||
library from sources: https://www.feaser.com/openblt/doku.php?id=manual:libopenblt.
|
||||
|
||||
\verbatim
|
||||
----------------------------------------------------------------------------------------
|
||||
C O P Y R I G H T
|
||||
----------------------------------------------------------------------------------------
|
||||
Copyright (c) 2017 Feaser. All rights reserved.
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
L I C E N S E
|
||||
----------------------------------------------------------------------------------------
|
||||
This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
----------------------------------------------------------------------------------------
|
||||
\endverbatim
|
||||
|
||||
*/
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/************************************************************************************//**
|
||||
* \file serialport.h
|
||||
* \brief Serial port header file.
|
||||
* \ingroup Session
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
#ifndef SERIALPORT_H
|
||||
#define SERIALPORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Enumaration of the supported baudrates. */
|
||||
typedef enum
|
||||
{
|
||||
SERIALPORT_BR9600 = 0, /**< 9600 bits/sec */
|
||||
SERIALPORT_BR19200 = 1, /**< 19200 bits/sec */
|
||||
SERIALPORT_BR38400 = 2, /**< 38400 bits/sec */
|
||||
SERIALPORT_BR57600 = 3, /**< 57600 bits/sec */
|
||||
SERIALPORT_BR115200 = 4 /**< 115200 bits/sec */
|
||||
} tSerialPortBaudrate;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
void SerialPortInit(void);
|
||||
void SerialPortTerminate(void);
|
||||
bool SerialPortOpen(char const * portname, tSerialPortBaudrate baudrate);
|
||||
void SerialPortClose(void);
|
||||
bool SerialPortWrite(uint8_t const * data, uint32_t length);
|
||||
bool SerialPortRead(uint8_t * data, uint32_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SERIALPORT_H */
|
||||
/********************************* end of serialport.h *********************************/
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
/************************************************************************************//**
|
||||
* \file session.c
|
||||
* \brief Communication session module source file.
|
||||
* \ingroup Session
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include "session.h" /* Communication session module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Pointer to the communication protocol that is linked. */
|
||||
static tSessionProtocol const * protocolPtr;
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the communication session module for the specified protocol.
|
||||
** \param protocol The session protocol module to link.
|
||||
** \param protocolSettings Pointer to structure with protocol specific settings.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SessionInit(tSessionProtocol const * protocol, void const * protocolSettings)
|
||||
{
|
||||
/* Check parameters. Note that the protocolSettings parameter is allowed to be NULL,
|
||||
* because not every protocol might need additional settings.
|
||||
*/
|
||||
assert(protocol != NULL);
|
||||
|
||||
/* Link the protocol module. */
|
||||
protocolPtr = protocol;
|
||||
|
||||
/* Initialize the protocol and pass on the settings pointer. */
|
||||
if (protocolPtr != NULL)
|
||||
{
|
||||
protocolPtr->Init(protocolSettings);
|
||||
}
|
||||
} /*** end of SessionInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the communication session module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SessionTerminate(void)
|
||||
{
|
||||
/* Terminate the linked protocol. */
|
||||
if (protocolPtr != NULL)
|
||||
{
|
||||
protocolPtr->Terminate();
|
||||
}
|
||||
/* Unlink the protocol module. */
|
||||
protocolPtr = NULL;
|
||||
} /*** end of SessionTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Starts the firmware update session. This is where the connection with the
|
||||
** target is made and the bootloader on the target is activated.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SessionStart(void)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Pass the request on to the linked protocol module. */
|
||||
if (protocolPtr != NULL)
|
||||
{
|
||||
result = protocolPtr->Start();
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SessionStart ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Stops the firmware update. This is where the bootloader starts the user
|
||||
** program on the target if a valid one is present. After this the connection
|
||||
** with the target is severed.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void SessionStop(void)
|
||||
{
|
||||
/* Pass the request on to the linked protocol module. */
|
||||
if (protocolPtr != NULL)
|
||||
{
|
||||
protocolPtr->Stop();
|
||||
}
|
||||
} /*** end of SessionStop ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Requests the bootloader to erase the specified range of memory on the
|
||||
** target. The bootloader aligns this range to hardware specified erase
|
||||
** blocks.
|
||||
** \param address The starting memory address for the erase operation.
|
||||
** \param len The total number of bytes to erase from memory.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SessionClearMemory(uint32_t address, uint32_t len)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if the parameters are vald. */
|
||||
if (len > 0)
|
||||
{
|
||||
/* Pass the request on to the linked protocol module. */
|
||||
result = protocolPtr->ClearMemory(address, len);
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SessionClearMemory ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Requests the bootloader to program the specified data to memory. In case of
|
||||
** non-volatile memory, the application needs to make sure the memory range
|
||||
** was erased beforehand.
|
||||
** \param address The starting memory address for the write operation.
|
||||
** \param len The number of bytes in the data buffer that should be written.
|
||||
** \param data Pointer to the byte array with data to write.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SessionWriteData(uint32_t address, uint32_t len, uint8_t const * data)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the linked protocol module. */
|
||||
result = protocolPtr->WriteData(address, len, data);
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SessionWriteData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Request the bootloader to upload the specified range of memory. The data is
|
||||
** stored in the data byte array to which the pointer was specified.
|
||||
** \param address The starting memory address for the read operation.
|
||||
** \param len The number of bytes to upload from the target and store in the data
|
||||
** buffer.
|
||||
** \param data Pointer to the byte array where the uploaded data should be stored.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool SessionReadData(uint32_t address, uint32_t len, uint8_t * data)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Pass the request on to the linked protocol module. */
|
||||
result = protocolPtr->ReadData(address, len, data);
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SessionReadData ***/
|
||||
|
||||
/*********************************** end of session.c **********************************/
|
|
@ -0,0 +1,101 @@
|
|||
/************************************************************************************//**
|
||||
* \file session.h
|
||||
* \brief Communication session module header file.
|
||||
* \ingroup Session
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
* \defgroup Session Communication Session Module
|
||||
* \brief Module with functionality to communicate with the bootloader on the target
|
||||
* system.
|
||||
* \ingroup Library
|
||||
* \details
|
||||
* The Communication Session module handles the communication with the bootloader during
|
||||
* firmware updates on the target system. It contains an interface to link the desired
|
||||
* communication protocol that should be used for the communication. For example the XCP
|
||||
* protocol.
|
||||
****************************************************************************************/
|
||||
#ifndef SESSION_H
|
||||
#define SESSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Session communication protocol interface. */
|
||||
typedef struct t_session_protocol
|
||||
{
|
||||
/** \brief Initializes the protocol module. */
|
||||
void (* Init) (void const * settings);
|
||||
/** \brief Terminates the protocol module. */
|
||||
void (* Terminate) (void);
|
||||
/** \brief Starts the firmware update session. This is where the connection with the
|
||||
* target is made and the bootloader on the target is activated.
|
||||
*/
|
||||
bool (* Start) (void);
|
||||
/** \brief Stops the firmware update. This is where the bootloader starts the user
|
||||
* program on the target if a valid one is present. After this the connection
|
||||
* with the target is severed.
|
||||
*/
|
||||
void (* Stop) (void);
|
||||
/** \brief Requests the bootloader to erase the specified range of memory on the
|
||||
* target. The bootloader aligns this range to hardware specified erase blocks.
|
||||
*/
|
||||
bool (* ClearMemory) (uint32_t address, uint32_t len);
|
||||
/** \brief Requests the bootloader to program the specified data to memory. In case of
|
||||
* non-volatile memory, the application needs to make sure the memory range
|
||||
* was erased beforehand.
|
||||
*/
|
||||
bool (* WriteData) (uint32_t address, uint32_t len, uint8_t const * data);
|
||||
/** \brief Request the bootloader to upload the specified range of memory. The data is
|
||||
* stored in the data byte array to which the pointer was specified.
|
||||
*/
|
||||
bool (* ReadData) (uint32_t address, uint32_t len, uint8_t * data);
|
||||
} tSessionProtocol;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
void SessionInit(tSessionProtocol const * protocol, void const * protocolSettings);
|
||||
void SessionTerminate(void);
|
||||
bool SessionStart(void);
|
||||
void SessionStop(void);
|
||||
bool SessionClearMemory(uint32_t address, uint32_t len);
|
||||
bool SessionWriteData(uint32_t address, uint32_t len, uint8_t const * data);
|
||||
bool SessionReadData(uint32_t address, uint32_t len, uint8_t * data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SESSION_H */
|
||||
/********************************* end of session.h ************************************/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,800 @@
|
|||
/************************************************************************************//**
|
||||
* \file srecparser.c
|
||||
* \brief Motorola S-record file parser source file.
|
||||
* \ingroup Firmware
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <stdio.h> /* for standard I/O library */
|
||||
#include <string.h> /* for string library */
|
||||
#include <ctype.h> /* for toupper() etc. */
|
||||
#include "util.h" /* Utility module */
|
||||
#include "firmware.h" /* Firmware data module */
|
||||
#include "srecparser.h" /* S-record parser */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Enumeration for the different supported S-record line types. */
|
||||
typedef enum t_srec_parser_line_type
|
||||
{
|
||||
SREC_PARSER_LINE_TYPE_S0, /**< Header record. */
|
||||
SREC_PARSER_LINE_TYPE_S1, /**< 16-bit address data record. */
|
||||
SREC_PARSER_LINE_TYPE_S2, /**< 24-bit address data record. */
|
||||
SREC_PARSER_LINE_TYPE_S3, /**< 32-bit address data record. */
|
||||
SREC_PARSER_LINE_TYPE_S7, /**< 32-bit address termination. */
|
||||
SREC_PARSER_LINE_TYPE_S8, /**< 24-bit address termination. */
|
||||
SREC_PARSER_LINE_TYPE_S9, /**< 16-bit address termination. */
|
||||
SREC_PARSER_LINE_TYPE_UNSUPPORTED /**< Unsupported line. */
|
||||
} tSRecParserLineType;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
static bool SRecParserLoadFromFile (char const * firmwareFile);
|
||||
static bool SRecParserSaveToFile (char const * firmwareFile);
|
||||
static bool SRecParserExtractLineData(char const * line, uint32_t * address,
|
||||
uint32_t * len, uint8_t * data);
|
||||
static tSRecParserLineType SRecParserGetLineType(char const * line);
|
||||
static bool SRecParserVerifyChecksum(char const * line);
|
||||
static bool SRecParserConstructLine(char * line, tSRecParserLineType lineType,
|
||||
uint32_t address,
|
||||
uint8_t const * data, uint8_t dataLen);
|
||||
static uint8_t SRecParserHexStringToByte(char const * hexstring);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local constant declarations
|
||||
****************************************************************************************/
|
||||
/** \brief File parser structure filled with Motorola S-record parsing specifics. */
|
||||
static const tFirmwareParser srecParser =
|
||||
{
|
||||
.LoadFromFile = SRecParserLoadFromFile,
|
||||
.SaveToFile = SRecParserSaveToFile
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************************//**
|
||||
** \brief Obtains a pointer to the parser structure, so that it can be linked to the
|
||||
** firmware data module.
|
||||
** \return Pointer to firmware parser structure.
|
||||
**
|
||||
****************************************************************************************/
|
||||
tFirmwareParser const * SRecParserGetParser(void)
|
||||
{
|
||||
return &srecParser;
|
||||
} /*** end of SRecParserGetParser ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Parses the specified firmware file to extract firmware data and adds this
|
||||
** data to the firmware data that is currently managed by the firmware data
|
||||
** module.
|
||||
** \param firmwareFile Filename of the firmware file to load.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool SRecParserLoadFromFile (char const * firmwareFile)
|
||||
{
|
||||
bool result = false;
|
||||
FILE *fp;
|
||||
/* The bytes count entry on the S-record line is max 255 bytes. This include the
|
||||
* address and the checksum. This would result in 255 * 2 = 510 characters. Another
|
||||
* 4 characters are needed for the bytes count and line type characters. Then another
|
||||
* two for possible line termination (new line + cariage return). This brings the total
|
||||
* characters to 516. Note that this array was made static to lower the stack load.
|
||||
*/
|
||||
static char line[516];
|
||||
/* The bytes count entry on the S-record line is max 255 bytes. This includes the
|
||||
* address and checksum. This means the worst case max data bytes per line is 255 - 3.
|
||||
* Note that this array was made static to lower the stack load.
|
||||
*/
|
||||
static uint8_t data[252];
|
||||
uint32_t address;
|
||||
uint32_t len;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(firmwareFile != NULL);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if (firmwareFile != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Open the file for reading. */
|
||||
fp = fopen(firmwareFile, "r");
|
||||
/* Only continue if the filepointer is valid. */
|
||||
if (fp != NULL)
|
||||
{
|
||||
/* Start at the beginning of the file. */
|
||||
rewind(fp);
|
||||
/* Assume that everyting goes okay and then only set a negative result value upon
|
||||
* detection of a problem.
|
||||
*/
|
||||
result = true;
|
||||
/* Read the entire file, one line at a time. */
|
||||
while (fgets(line, sizeof(line)/sizeof(line[0]), fp) != NULL )
|
||||
{
|
||||
/* Replace the line termination with a string termination. */
|
||||
line[strcspn(line, "\n\r")] = '\0';
|
||||
/* Extra data from the S-record line. */
|
||||
if (SRecParserExtractLineData(line, &address, &len, data))
|
||||
{
|
||||
/* Only add data if there is actually something to add. */
|
||||
if (len > 0)
|
||||
{
|
||||
/* Add the extracted data to the firmware data module. */
|
||||
if (!FirmwareAddData(address, len, data))
|
||||
{
|
||||
/* Error detected. Flag it and abort. */
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Close the file now that we are done with it. */
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SRecParserLoadFromFile ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Writes firmware data to the specified file in the correct file format.
|
||||
** \param firmwareFile Filename of the firmware file to write to.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool SRecParserSaveToFile (char const * firmwareFile)
|
||||
{
|
||||
bool result = false;
|
||||
FILE *fp;
|
||||
/* The bytes count entry on the S-record line is max 255 bytes. This include the
|
||||
* address and the checksum. This would result in 255 * 2 = 510 characters. Another
|
||||
* 4 characters are needed for the bytes count and line type characters. Then another
|
||||
* two for possible line termination (new line + cariage return). This brings the total
|
||||
* characters to 516. Note that this array was made static to lower the stack load.
|
||||
*/
|
||||
static char line[516];
|
||||
/* The bytes count entry on the S-record line is max 255 bytes. This includes the
|
||||
* address and checksum. This means the worst case max data bytes per line is 255 - 3.
|
||||
* Note that this array was made static to lower the stack load.
|
||||
*/
|
||||
static uint8_t data[252];
|
||||
tFirmwareSegment * segment;
|
||||
uint32_t progDataLowestAddress = 0x00000000;
|
||||
uint32_t progDataHighestAddress = 0xffffffff;
|
||||
tSRecParserLineType dataLineType = SREC_PARSER_LINE_TYPE_S1;
|
||||
tSRecParserLineType terminationLineType = SREC_PARSER_LINE_TYPE_S9;
|
||||
uint32_t segmentIdx;
|
||||
uint32_t currentAddress;
|
||||
uint8_t currentByteCnt;
|
||||
uint8_t const * currentDataPtr;
|
||||
uint32_t segmentBytesLeft;
|
||||
const uint8_t maxDataBytesPerLine = 32;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(firmwareFile != NULL);
|
||||
|
||||
/* Only continue if the parameters are valid and if there is something to save. */
|
||||
if ( (firmwareFile != NULL) && (FirmwareGetSegmentCount() > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Open the file for writing. */
|
||||
fp = fopen(firmwareFile, "w");
|
||||
/* Only continue if the filepointer is valid. */
|
||||
if (fp != NULL)
|
||||
{
|
||||
/* Init result value to okay at this point and only set it to error in case a
|
||||
* problem was detected.
|
||||
*/
|
||||
result = true;
|
||||
|
||||
/* Determine the lowest memory address used in the program data. This address needs
|
||||
* to be specified in the termination record at the end of the S-record file.
|
||||
*/
|
||||
segment = FirmwareGetSegment(0);
|
||||
/* Sanity check. */
|
||||
assert(segment != NULL);
|
||||
if (segment == NULL) /*lint !e774 */
|
||||
{
|
||||
/* Flag error. */
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Store the lowest memory address. */
|
||||
progDataLowestAddress = segment->base;
|
||||
}
|
||||
|
||||
/* Determine the highest memory address used in the program data. This address
|
||||
* is needed to determine the number of bits needed for the address in the
|
||||
* S-record data lines (16, 24 or 32), which determines the type of S-record for
|
||||
* the data lines (S1, S2, S3) and the termination line (S7, S8 or S9).
|
||||
*/
|
||||
if (result) /*lint !e774 */
|
||||
{
|
||||
segment = FirmwareGetSegment(FirmwareGetSegmentCount() - 1u);
|
||||
/* Sanity check. */
|
||||
assert(segment != NULL);
|
||||
if (segment == NULL) /*lint !e774 */
|
||||
{
|
||||
/* Flag error. */
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
progDataHighestAddress = segment->base + segment->length - 1u;
|
||||
/* Does the address have more than 24 bits? */
|
||||
if (progDataHighestAddress > 0xffffff)
|
||||
{
|
||||
dataLineType = SREC_PARSER_LINE_TYPE_S3;
|
||||
terminationLineType = SREC_PARSER_LINE_TYPE_S7;
|
||||
}
|
||||
/* Does the address have more than 16 bits? */
|
||||
else if (progDataHighestAddress > 0xffff)
|
||||
{
|
||||
dataLineType = SREC_PARSER_LINE_TYPE_S2;
|
||||
terminationLineType = SREC_PARSER_LINE_TYPE_S8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract just the filename and copy it to the data buffer. */
|
||||
if (result) /*lint !e774 */
|
||||
{
|
||||
if (!UtilFileExtractFilename(firmwareFile, (char *)data))
|
||||
{
|
||||
/* Could not extract filename. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct and add the S0-record with the filename. */
|
||||
if (result)
|
||||
{
|
||||
/* Construct the S0-record. */
|
||||
result = SRecParserConstructLine(line, SREC_PARSER_LINE_TYPE_S0, 0x0000, data,
|
||||
(uint8_t)strlen((char *)data));
|
||||
if (result)
|
||||
{
|
||||
/* Add the S0-record. */
|
||||
if (fprintf(fp, "%s\r\n", line) < 0)
|
||||
{
|
||||
/* Could not write line to the file. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write all the program data records. Process one segment at a time. */
|
||||
if (result)
|
||||
{
|
||||
/* Loop through all segments. */
|
||||
for (segmentIdx = 0; segmentIdx < FirmwareGetSegmentCount(); segmentIdx++)
|
||||
{
|
||||
/* Obtain the segment. */
|
||||
segment = FirmwareGetSegment(segmentIdx);
|
||||
/* Sanity check. */
|
||||
assert(segment != NULL);
|
||||
if (segment == 0) /*lint !e774 */
|
||||
{
|
||||
/* Flag error and abort loop. */
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
/* Initialize base address, byte count and data pointer. */
|
||||
currentAddress = segment->base;
|
||||
currentDataPtr = segment->data;
|
||||
segmentBytesLeft = segment->length;
|
||||
/* Process al bytes in the segment. */
|
||||
while (segmentBytesLeft > 0)
|
||||
{
|
||||
/* Determine the number of bytes that can be written. */
|
||||
currentByteCnt = maxDataBytesPerLine;
|
||||
if (segmentBytesLeft < maxDataBytesPerLine)
|
||||
{
|
||||
currentByteCnt = (uint8_t)segmentBytesLeft;
|
||||
}
|
||||
/* Construct the data record. */
|
||||
result = SRecParserConstructLine(line, dataLineType, currentAddress,
|
||||
currentDataPtr, currentByteCnt);
|
||||
if (!result)
|
||||
{
|
||||
/* Error detected. No need to continue the loop. */
|
||||
break;
|
||||
}
|
||||
/* Add the data record. */
|
||||
if (fprintf(fp, "%s\r\n", line) < 0)
|
||||
{
|
||||
/* Could not write line to the file. Abort loop. */
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
/* Update loop variables. */
|
||||
currentAddress += currentByteCnt;
|
||||
currentDataPtr += currentByteCnt;
|
||||
segmentBytesLeft -= currentByteCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the termination record. */
|
||||
if (result)
|
||||
{
|
||||
/* Construct the termination record. */
|
||||
result = SRecParserConstructLine(line, terminationLineType,
|
||||
progDataLowestAddress, data, 0u);
|
||||
if (result)
|
||||
{
|
||||
/* Add the termination record. */
|
||||
if (fprintf(fp, "%s\r\n", line) < 0)
|
||||
{
|
||||
/* Could not write line to the file. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SRecParserSaveToFile ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Checks if the specified S-record line is of the type that contains program
|
||||
** data. If it does, then the program data and base address are extracted and
|
||||
** stored at the function parameter pointers.
|
||||
** \param line Pointer to the line from an S-record file.
|
||||
** \param address Pointer where the start address of the program data is stored.
|
||||
** \param len Pointer for storing the number of extracted program data bytes.
|
||||
** \param data Pointer to byte array where the extracted program data bytes are
|
||||
** stored.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool SRecParserExtractLineData(char const * line, uint32_t * address,
|
||||
uint32_t * len, uint8_t * data)
|
||||
{
|
||||
bool result = false;
|
||||
tSRecParserLineType lineType;
|
||||
uint8_t dataByteCount = 0;
|
||||
uint8_t bytesOnLine;
|
||||
uint8_t idx;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(line != NULL);
|
||||
assert(address != NULL);
|
||||
assert(len != NULL);
|
||||
assert(data != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if ( (line != NULL) && (address != NULL) && (len != NULL) &&
|
||||
(data != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Determine the line type. */
|
||||
lineType = SRecParserGetLineType(line);
|
||||
/* Only continue if the S-record line contains program data. */
|
||||
if ( (lineType == SREC_PARSER_LINE_TYPE_S1) ||
|
||||
(lineType == SREC_PARSER_LINE_TYPE_S2) ||
|
||||
(lineType == SREC_PARSER_LINE_TYPE_S3) )
|
||||
{
|
||||
/* Verify the checksum of the line. */
|
||||
if (SRecParserVerifyChecksum(line))
|
||||
{
|
||||
/* Adjust pointer to point to byte count value. */
|
||||
line += 2u;
|
||||
/* Read out the number of byte values that follow on the line. */
|
||||
bytesOnLine = SRecParserHexStringToByte(line);
|
||||
/* Process S1 line type. */
|
||||
if (lineType == SREC_PARSER_LINE_TYPE_S1)
|
||||
{
|
||||
/* Read out the 16-bit address. */
|
||||
line += 2u;
|
||||
*address = (uint32_t)SRecParserHexStringToByte(line) << 8u;
|
||||
line += 2u;
|
||||
*address += (uint32_t)SRecParserHexStringToByte(line);
|
||||
/* Determine how many data bytes are on the line. -2 bytes for address and
|
||||
* -1 byte for the checksum.
|
||||
*/
|
||||
dataByteCount = bytesOnLine - 3u;
|
||||
}
|
||||
/* Process S2 line type. */
|
||||
else if (lineType == SREC_PARSER_LINE_TYPE_S2)
|
||||
{
|
||||
/* Read out the 24-bit address. */
|
||||
line += 2u;
|
||||
*address = (uint32_t)SRecParserHexStringToByte(line) << 16u;
|
||||
line += 2u;
|
||||
*address += (uint32_t)SRecParserHexStringToByte(line) << 8u;
|
||||
line += 2u;
|
||||
*address += (uint32_t)SRecParserHexStringToByte(line);
|
||||
/* Determine how many data bytes are on the line. -3 bytes for address and
|
||||
* -1 byte for the checksum.
|
||||
*/
|
||||
dataByteCount = bytesOnLine - 4u;
|
||||
}
|
||||
/* Process S3 line type. */
|
||||
else
|
||||
{
|
||||
/* Read out the 32-bit address. */
|
||||
line += 2u;
|
||||
*address = (uint32_t)SRecParserHexStringToByte(line) << 24u;
|
||||
line += 2u;
|
||||
*address += (uint32_t)SRecParserHexStringToByte(line) << 16u;
|
||||
line += 2u;
|
||||
*address += (uint32_t)SRecParserHexStringToByte(line) << 8u;
|
||||
line += 2u;
|
||||
*address += (uint32_t)SRecParserHexStringToByte(line);
|
||||
/* Determine how many data bytes are on the line. -4 bytes for address and
|
||||
* -1 byte for the checksum.
|
||||
*/
|
||||
dataByteCount = bytesOnLine - 5u;
|
||||
}
|
||||
/* Adjust pointer to point to the first data byte after the address. */
|
||||
line += 2u;
|
||||
/* Read and store data bytes. */
|
||||
for (idx = 0; idx < dataByteCount; idx++)
|
||||
{
|
||||
data[idx] = SRecParserHexStringToByte(line);
|
||||
line += 2u;
|
||||
}
|
||||
/* Store the number of data bytes that were copied to the array. */
|
||||
*len = dataByteCount;
|
||||
/* Data extraction complete. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SRecParserExtractLineData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Inspects a line from a Motorola S-Record file to determine its type.
|
||||
** \param line A line from the S-Record.
|
||||
** \return The S-Record line type.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static tSRecParserLineType SRecParserGetLineType(char const * line)
|
||||
{
|
||||
tSRecParserLineType result = SREC_PARSER_LINE_TYPE_UNSUPPORTED;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(line != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if (line != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Check if the line starts with the 'S' character, followed by a digit */
|
||||
if ( (toupper((int32_t)(line[0])) == 'S') && (isdigit((int32_t)(line[1]))) )
|
||||
{
|
||||
/* Check the digit that follows the 'S' character. Currently only line types that
|
||||
* contain program data are needed.
|
||||
*/
|
||||
switch (line[1])
|
||||
{
|
||||
case '0':
|
||||
result = SREC_PARSER_LINE_TYPE_S0;
|
||||
break;
|
||||
case '1':
|
||||
result = SREC_PARSER_LINE_TYPE_S1;
|
||||
break;
|
||||
case '2':
|
||||
result = SREC_PARSER_LINE_TYPE_S2;
|
||||
break;
|
||||
case '3':
|
||||
result = SREC_PARSER_LINE_TYPE_S3;
|
||||
break;
|
||||
case '7':
|
||||
result = SREC_PARSER_LINE_TYPE_S7;
|
||||
break;
|
||||
case '8':
|
||||
result = SREC_PARSER_LINE_TYPE_S8;
|
||||
break;
|
||||
case '9':
|
||||
result = SREC_PARSER_LINE_TYPE_S9;
|
||||
break;
|
||||
default:
|
||||
result = SREC_PARSER_LINE_TYPE_UNSUPPORTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SRecParserGetLineType ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Inspects an S1, S2 or S3 line from a Motorola S-Record file to
|
||||
** determine if the checksum at the end is corrrect.
|
||||
** \param line An S1, S2 or S3 line from the S-Record.
|
||||
** \return True if the checksum is correct, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool SRecParserVerifyChecksum(char const * line)
|
||||
{
|
||||
bool result = false;
|
||||
uint8_t bytes_on_line;
|
||||
uint8_t checksum = 0;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(line != NULL);
|
||||
/* Only continue with with valid parameters. */
|
||||
if (line != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Adjust pointer to point to byte count value. */
|
||||
line += 2u;
|
||||
/* Read out the number of byte values that follow on the line. */
|
||||
bytes_on_line = SRecParserHexStringToByte(line);
|
||||
/* An S-record will always have at least a 16-bit address and a checksum value. */
|
||||
if (bytes_on_line >= 3u)
|
||||
{
|
||||
/* Byte count is part of checksum. */
|
||||
checksum += bytes_on_line;
|
||||
/* Adjust pointer to the first byte of the address. */
|
||||
line += 2u;
|
||||
/* Add byte values of address and data, but not the final checksum. */
|
||||
do
|
||||
{
|
||||
/* Add the next byte value to the checksum. */
|
||||
checksum += SRecParserHexStringToByte(line);
|
||||
/* Update counter. */
|
||||
bytes_on_line--;
|
||||
/* Point to next hex string in the line. */
|
||||
line += 2u;
|
||||
}
|
||||
while (bytes_on_line > 1u);
|
||||
/* The checksum is calculated by summing up the values of the byte count, address
|
||||
* and databytes and then taking the 1-complement of the sum's least signigicant
|
||||
* byte.
|
||||
*/
|
||||
checksum = ~checksum;
|
||||
/* Finally verify the calculated checksum with the one at the end of the line. */
|
||||
if (checksum == SRecParserHexStringToByte(line))
|
||||
{
|
||||
/* Checksum correct. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SRecParserVerifyChecksum ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Creates a NUL terminated S-record line, given the specified line type,
|
||||
** address and data bytes. The checksum at the end of the line is also
|
||||
** calculated and added.
|
||||
** \param line Pointer to character array where the string will be stored.
|
||||
** \param lineType The type of S-record line to construct.
|
||||
** \param address The address to embed into the line after the byte count.
|
||||
** \param data Point to byte array with data bytes to add to the line.
|
||||
** \param dataLen The number of data bytes present in the data-array.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool SRecParserConstructLine(char * line, tSRecParserLineType lineType,
|
||||
uint32_t address, uint8_t const * data,
|
||||
uint8_t dataLen)
|
||||
{
|
||||
bool result = false;
|
||||
uint8_t addressBits;
|
||||
uint8_t byteVal;
|
||||
char hexByteStr[3];
|
||||
uint8_t cnt;
|
||||
uint8_t checksumVal = 0;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(line != NULL);
|
||||
if (dataLen > 0)
|
||||
{
|
||||
assert(data != NULL);
|
||||
}
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if (line != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Set the result value to successful and only change this upon detection of an
|
||||
* error.
|
||||
*/
|
||||
result = true;
|
||||
/* Start of with an empty string. */
|
||||
line[0] = '\0';
|
||||
/* Add the record type based on the lineType and store the number of bits in the
|
||||
* address.
|
||||
*/
|
||||
switch (lineType)
|
||||
{
|
||||
case SREC_PARSER_LINE_TYPE_S0:
|
||||
strcat(line, "S0");
|
||||
addressBits = 16;
|
||||
break;
|
||||
case SREC_PARSER_LINE_TYPE_S1:
|
||||
strcat(line, "S1");
|
||||
addressBits = 16;
|
||||
break;
|
||||
case SREC_PARSER_LINE_TYPE_S2:
|
||||
strcat(line, "S2");
|
||||
addressBits = 24;
|
||||
break;
|
||||
case SREC_PARSER_LINE_TYPE_S3:
|
||||
strcat(line, "S3");
|
||||
addressBits = 32;
|
||||
break;
|
||||
case SREC_PARSER_LINE_TYPE_S7:
|
||||
strcat(line, "S7");
|
||||
addressBits = 32;
|
||||
break;
|
||||
case SREC_PARSER_LINE_TYPE_S8:
|
||||
strcat(line, "S8");
|
||||
addressBits = 24;
|
||||
break;
|
||||
case SREC_PARSER_LINE_TYPE_S9:
|
||||
strcat(line, "S9");
|
||||
addressBits = 16;
|
||||
break;
|
||||
case SREC_PARSER_LINE_TYPE_UNSUPPORTED:
|
||||
default:
|
||||
/* Invalid line type specified. Should not happed. */
|
||||
addressBits = 16;
|
||||
assert(false); /*lint !e506 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next, add the number of bytes that will follow on the line. This is the size in
|
||||
* bytes of the address, the actual number of data bytes and the checksum.
|
||||
*/
|
||||
byteVal = (addressBits / 8u) + dataLen + 1u;
|
||||
checksumVal += byteVal;
|
||||
if (sprintf(hexByteStr, "%02X", byteVal) != 2)
|
||||
{
|
||||
/* Error occurred. */
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Append it to the line. */
|
||||
strcat(line, hexByteStr);
|
||||
}
|
||||
|
||||
/* Add the address. */
|
||||
for (cnt = (addressBits / 8u); cnt > 0; cnt--)
|
||||
{
|
||||
byteVal = (uint8_t)(address >> ( (cnt - 1u) * 8u));
|
||||
checksumVal += byteVal;
|
||||
if (sprintf(hexByteStr, "%02X", byteVal) != 2)
|
||||
{
|
||||
/* Error occurred. */
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Append it to the line. */
|
||||
strcat(line, hexByteStr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the data bytes. */
|
||||
for (cnt = 0; cnt < dataLen; cnt++)
|
||||
{
|
||||
byteVal = 0;
|
||||
if (data != NULL)
|
||||
{
|
||||
byteVal = data[cnt];
|
||||
}
|
||||
checksumVal += byteVal;
|
||||
if (sprintf(hexByteStr, "%02X", byteVal) != 2)
|
||||
{
|
||||
/* Error occurred. */
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Append it to the line. */
|
||||
strcat(line, hexByteStr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate and add the checksum. */
|
||||
checksumVal = ~checksumVal;
|
||||
byteVal = checksumVal;
|
||||
if (sprintf(hexByteStr, "%02X", byteVal) != 2)
|
||||
{
|
||||
/* Error occurred. */
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Append it to the line. */
|
||||
strcat(line, hexByteStr);
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SRecParserConstructLine ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Helper function to convert a sequence of 2 characters that represent
|
||||
** a hexadecimal value to the actual byte value.
|
||||
** Example: SRecParserHexStringToByte("2f") --> returns 47.
|
||||
** \param hexstring String beginning with 2 characters that represent a hexa-
|
||||
** decimal value.
|
||||
** \return The resulting byte value.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static uint8_t SRecParserHexStringToByte(char const * hexstring)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
int32_t c;
|
||||
uint8_t counter;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(hexstring != NULL);
|
||||
/* Only continue with valid parameters. */
|
||||
if (hexstring != NULL) /*lint !e774 */
|
||||
{
|
||||
/* A hexadecimal character is 2 characters long (i.e 0x4F minus the 0x part). */
|
||||
for (counter = 0; counter < 2u; counter++)
|
||||
{
|
||||
/* Read out the character */
|
||||
c = toupper((int32_t)(hexstring[counter]));
|
||||
/* Check that the character is 0..9 or A..F */
|
||||
if (isxdigit(c))
|
||||
{
|
||||
/* Convert character to 4-bit value (check ASCII table for more info) */
|
||||
c -= '0';
|
||||
if (c > 9)
|
||||
{
|
||||
c -= 7;
|
||||
}
|
||||
/* Add it to the result. */
|
||||
result = (uint8_t)((result << 4u) + c);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of SRecParserHexStringToByte ***/
|
||||
|
||||
|
||||
/*********************************** end of srecparser.c *******************************/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/************************************************************************************//**
|
||||
* \file srecparser.h
|
||||
* \brief Motorola S-record file parser header file.
|
||||
* \ingroup Firmware
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
#ifndef SRECPARSER_H
|
||||
#define SRECPARSER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
tFirmwareParser const * SRecParserGetParser(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SRECPARSER_H */
|
||||
/********************************* end of srecparser.h *********************************/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
/************************************************************************************//**
|
||||
* \file util.c
|
||||
* \brief Utility module source file.
|
||||
* \ingroup Utility
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <string.h> /* for string library */
|
||||
#include "util.h" /* Utility module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local constant declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Lookup table for calculating a 16-bit CRC checksum. It was generated using an
|
||||
* initial value of 0 and a polynomial of 0x8005.
|
||||
*/
|
||||
static const uint16_t utilChecksumCrc16Table[256] =
|
||||
{
|
||||
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
|
||||
0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
|
||||
0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
|
||||
0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
|
||||
0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
|
||||
0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
|
||||
0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
|
||||
0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
|
||||
0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
|
||||
0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
|
||||
0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
|
||||
0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
|
||||
0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
|
||||
0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
|
||||
0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
|
||||
0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
|
||||
0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
|
||||
0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
|
||||
0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
|
||||
0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
|
||||
0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
|
||||
0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
|
||||
0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
|
||||
0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
|
||||
0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
|
||||
0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
|
||||
0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
|
||||
0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
|
||||
0x8243, 0x2046, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
|
||||
0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
|
||||
0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
|
||||
0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
|
||||
};
|
||||
|
||||
/** \brief Lookup table for calculating a 32-bit CRC checksum. It was generated using an
|
||||
* initial value of 0 and a polynomial of 0x04C11DB7
|
||||
*/
|
||||
static const uint32_t utilChecksumCrc32Table[256] =
|
||||
{
|
||||
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2,
|
||||
0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3,
|
||||
0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
|
||||
0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011,
|
||||
0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E,
|
||||
0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF,
|
||||
0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90,
|
||||
0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
|
||||
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A,
|
||||
0xEC7DD02D, 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C,
|
||||
0x2E003DC5, 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13,
|
||||
0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
|
||||
0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
|
||||
0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 0xACA5C697, 0xA864DB20,
|
||||
0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F,
|
||||
0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
|
||||
0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055,
|
||||
0xFEF34DE2, 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
|
||||
0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632,
|
||||
0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F,
|
||||
0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629, 0x2C9F00F0,
|
||||
0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91,
|
||||
0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
|
||||
0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
|
||||
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604,
|
||||
0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615,
|
||||
0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A,
|
||||
0x8CF30BAD, 0x81B02D74, 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
|
||||
0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F,
|
||||
0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E,
|
||||
0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, 0x3793A651,
|
||||
0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
|
||||
0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
|
||||
0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA,
|
||||
0xF9278673, 0xFDE69BC4, 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5,
|
||||
0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
|
||||
0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Calculates a 16-bit CRC value over the specified data using byte wise
|
||||
** computation with a table.
|
||||
** \param data Array with bytes over which the CRC16 should be calculated.
|
||||
** \param len Number of bytes in the data array.
|
||||
** \return The 16-bit CRC value.
|
||||
**
|
||||
****************************************************************************************/
|
||||
uint16_t UtilChecksumCrc16Calculate(uint8_t const * data, uint32_t len)
|
||||
{
|
||||
uint16_t result = 0;
|
||||
uint32_t byteIdx;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Loop through all bytes. */
|
||||
for (byteIdx = 0; byteIdx < len; byteIdx++)
|
||||
{
|
||||
result = ((uint16_t)(result << 8)) ^
|
||||
utilChecksumCrc16Table[(uint8_t)(data[byteIdx] ^ (result >> 8))];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} /*** end of UtilChecksumCrc16Calculate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Calculates a 32-bit CRC value over the specified data using byte wise
|
||||
** computation with a table.
|
||||
** \param data Array with bytes over which the CRC32 should be calculated.
|
||||
** \param len Number of bytes in the data array.
|
||||
** \return The 32-bit CRC value.
|
||||
**
|
||||
****************************************************************************************/
|
||||
uint32_t UtilChecksumCrc32Calculate(uint8_t const * data, uint32_t len)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
uint32_t byteIdx;
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
|
||||
/* Only continue if parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) ) /*lint !e774 */
|
||||
{
|
||||
/* Loop through all bytes. */
|
||||
for (byteIdx = 0; byteIdx < len; byteIdx++)
|
||||
{
|
||||
result = ((uint32_t)(result << 8)) ^
|
||||
utilChecksumCrc32Table[(uint8_t)(data[byteIdx] ^ (result >> 24))];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} /*** end of UtilChecksumCrc32Calculate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Extracts the filename including extention from the specified full filename,
|
||||
** which could possible include a path. The function can handle both the
|
||||
** backslash and forward slash path delimiter, to make it crossplatform.
|
||||
** \param fullFilename The filename with path possible included.
|
||||
** \param filenameBuffer Pointer to the character array where the resulting filename
|
||||
** should be stored.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool UtilFileExtractFilename(char const * fullFilename, char * filenameBuffer)
|
||||
{
|
||||
bool result = false;
|
||||
char const * filenamePtr;
|
||||
|
||||
|
||||
/* Verify parameters. */
|
||||
assert(fullFilename != NULL);
|
||||
assert(filenameBuffer != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if ( (fullFilename != NULL) && (filenameBuffer != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Extract just the filename, so without its path from the firmware file. First
|
||||
* assume a unix type path with forward slashes.
|
||||
*/
|
||||
filenamePtr = strrchr(fullFilename, '/');
|
||||
/* Check if a forward slash was detected. */
|
||||
if (filenamePtr != NULL)
|
||||
{
|
||||
/* Update the pointer so that it point to the start of the filename. */
|
||||
filenamePtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No unix type forward slash found. This can be because the path uses windows
|
||||
* type backslashes or because there is no path present and it is already just
|
||||
* the filename. Now check for a windows type path with backslashes.
|
||||
*/
|
||||
filenamePtr = strrchr(fullFilename, '\\');
|
||||
/* Check if a forward slash was detected. */
|
||||
if (filenamePtr != NULL)
|
||||
{
|
||||
/* Update the pointer so that it point to the start of the filename. */
|
||||
filenamePtr++;
|
||||
}
|
||||
/* In case no slashes were found in the firmware file, then it is already just the
|
||||
* filename.
|
||||
*/
|
||||
else
|
||||
{
|
||||
filenamePtr = fullFilename;
|
||||
}
|
||||
}
|
||||
/* Copy the resulting filename to the buffer. */
|
||||
strcpy(filenameBuffer, filenamePtr);
|
||||
/* Success. */
|
||||
result = true;
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of UtilFileExtractFilename ***/
|
||||
|
||||
|
||||
/*********************************** end of util.c *************************************/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/************************************************************************************//**
|
||||
* \file util.h
|
||||
* \brief Utility module header file.
|
||||
* \ingroup Utility
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
* \defgroup Utility Generic Utilities
|
||||
* \brief Generic utility functions and definitions.
|
||||
* \ingroup Library
|
||||
* \details
|
||||
* The Utility module contains generic functions and definitions that can be handy for
|
||||
* use internally in the library and also externally by another application that makes
|
||||
* use of the library.
|
||||
****************************************************************************************/
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
uint16_t UtilChecksumCrc16Calculate(uint8_t const * data, uint32_t len);
|
||||
uint32_t UtilChecksumCrc32Calculate(uint8_t const * data, uint32_t len);
|
||||
bool UtilFileExtractFilename(char const * fullFilename, char * filenameBuffer);
|
||||
uint32_t UtilTimeGetSystemTimeMs(void);
|
||||
void UtilTimeDelayMs(uint16_t delay);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* UTIL_H */
|
||||
/********************************* end of util.h ***************************************/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,971 @@
|
|||
/************************************************************************************//**
|
||||
* \file xcploader.c
|
||||
* \brief XCP Loader module source file.
|
||||
* \ingroup XcpLoader
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include "session.h" /* Communication session module */
|
||||
#include "xcploader.h" /* XCP loader module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/* XCP command codes as defined by the protocol currently supported by this module */
|
||||
#define XCPLOADER_CMD_CONNECT (0xFFu) /**< XCP connect command code. */
|
||||
#define XCPLOADER_CMD_SET_MTA (0xF6u) /**< XCP set mta command code. */
|
||||
#define XCPLOADER_CMD_UPLOAD (0xF5u) /**< XCP upload command code. */
|
||||
#define XCPLOADER_CMD_PROGRAM_START (0xD2u) /**< XCP program start command code. */
|
||||
#define XCPLOADER_CMD_PROGRAM_CLEAR (0xD1u) /**< XCP program clear command code. */
|
||||
#define XCPLOADER_CMD_PROGRAM (0xD0u) /**< XCP program command code. */
|
||||
#define XCPLOADER_CMD_PROGRAM_RESET (0xCFu) /**< XCP program reset command code. */
|
||||
#define XCPLOADER_CMD_PROGRAM_MAX (0xC9u) /**< XCP program max command code. */
|
||||
|
||||
/* XCP response packet IDs as defined by the protocol. */
|
||||
#define XCPLOADER_CMD_PID_RES (0xFFu) /**< positive response */
|
||||
|
||||
/** \brief Maximum timeout for the XCP connect command. */
|
||||
#define XCPLOADER_CONNECT_TIMEOUT_MS (20u)
|
||||
|
||||
/** \brief Number of retries to connect to the XCP slave. */
|
||||
#define XCPLOADER_CONNECT_RETRIES (5u)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
/* Protocol functions for linking to the session module. */
|
||||
static void XcpLoaderInit(void const * settings);
|
||||
static void XcpLoaderTerminate(void);
|
||||
static bool XcpLoaderStart(void);
|
||||
static void XcpLoaderStop(void);
|
||||
static bool XcpLoaderClearMemory(uint32_t address, uint32_t len);
|
||||
static bool XcpLoaderWriteData(uint32_t address, uint32_t len, uint8_t const * data);
|
||||
static bool XcpLoaderReadData(uint32_t address, uint32_t len, uint8_t * data);
|
||||
/* General module specific utility functions. */
|
||||
static void XcpLoaderSetOrderedLong(uint32_t value, uint8_t *data);
|
||||
/* XCP command functions. */
|
||||
static bool XcpLoaderSendCmdConnect(void);
|
||||
static bool XcpLoaderSendCmdSetMta(uint32_t address);
|
||||
static bool XcpLoaderSendCmdUpload(uint8_t * data, uint8_t length);
|
||||
static bool XcpLoaderSendCmdProgramStart(void);
|
||||
static bool XcpLoaderSendCmdProgramReset(void);
|
||||
static bool XcpLoaderSendCmdProgram(uint8_t length, uint8_t const * data);
|
||||
static bool XcpLoaderSendCmdProgramMax(uint8_t const * data);
|
||||
static bool XcpLoaderSendCmdProgramClear(uint32_t length);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local constant declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Protocol structure filled with XCP loader specifics. */
|
||||
static const tSessionProtocol xcpLoader =
|
||||
{
|
||||
.Init = XcpLoaderInit,
|
||||
.Terminate = XcpLoaderTerminate,
|
||||
.Start = XcpLoaderStart,
|
||||
.Stop = XcpLoaderStop,
|
||||
.ClearMemory = XcpLoaderClearMemory,
|
||||
.WriteData = XcpLoaderWriteData,
|
||||
.ReadData = XcpLoaderReadData
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief The settings that should be used by the XCP loader. */
|
||||
static tXcpLoaderSettings xcpSettings;
|
||||
|
||||
/** \brief Flag to keep track of the connection status. */
|
||||
static bool xcpConnected;
|
||||
|
||||
/** \brief Store the byte ordering of the XCP slave. */
|
||||
static bool xcpSlaveIsIntel;
|
||||
|
||||
/** \brief The max number of bytes in the command transmit object (master->slave). */
|
||||
static uint8_t xcpMaxCto;
|
||||
|
||||
/** \brief The max number of bytes in the command transmit object (master->slave) during
|
||||
* a programming session.
|
||||
*/
|
||||
static uint8_t xcpMaxProgCto;
|
||||
|
||||
/** \brief The max number of bytes in the data transmit object (slave->master). */
|
||||
static uint16_t xcpMaxDto;
|
||||
|
||||
|
||||
/***********************************************************************************//**
|
||||
** \brief Obtains a pointer to the protocol structure, so that it can be linked to
|
||||
** the communication session module.
|
||||
** \return Pointer to protocol structure.
|
||||
**
|
||||
****************************************************************************************/
|
||||
tSessionProtocol const * XcpLoaderGetProtocol(void)
|
||||
{
|
||||
return &xcpLoader;
|
||||
} /*** end of XcpLoaderGetProtocol ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the protocol module.
|
||||
** \param settings Pointer to the structure with protocol settings.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpLoaderInit(void const * settings)
|
||||
{
|
||||
/* Initialize locals. */
|
||||
xcpConnected = false;
|
||||
xcpSlaveIsIntel = false;
|
||||
xcpMaxCto = 0;
|
||||
xcpMaxProgCto = 0;
|
||||
xcpMaxDto = 0;
|
||||
|
||||
/* Check parameter. */
|
||||
assert(settings != NULL);
|
||||
|
||||
/* Only continue with valid parameter. */
|
||||
if (settings != NULL) /*lint !e774 */
|
||||
{
|
||||
/* shallow copy the XCP settings for later usage */
|
||||
xcpSettings = *(tXcpLoaderSettings *)settings;
|
||||
/* Check that a valid transport layer was specified. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
/* Only access the transport layer if it is valid. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Initialize the transport layer. */
|
||||
xcpSettings.transport->Init(xcpSettings.transportSettings);
|
||||
}
|
||||
/* Invalidate the transportSettings as it is probably no longer valid outside this
|
||||
* function scope and should also not be used anymore.
|
||||
*/
|
||||
xcpSettings.transportSettings = NULL;
|
||||
}
|
||||
} /*** end of XcpLoaderInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the protocol module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpLoaderTerminate(void)
|
||||
{
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Stop the session. */
|
||||
XcpLoaderStop();
|
||||
/* Terminate the transport layer. */
|
||||
xcpSettings.transport->Terminate();
|
||||
/* Unlink the transport layer. */
|
||||
xcpSettings.transport = NULL;
|
||||
}
|
||||
} /*** end of XcpLoaderTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Starts the firmware update session. This is where the connection with the
|
||||
** target is made and the bootloader on the target is activated.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderStart(void)
|
||||
{
|
||||
bool result = false;
|
||||
uint8_t retryCnt;
|
||||
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Make sure the session is stopped before starting a new one. */
|
||||
XcpLoaderStop();
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Connect the transport layer. */
|
||||
if (!xcpSettings.transport->Connect())
|
||||
{
|
||||
/* Could not connect the transport layer. */
|
||||
result = false;
|
||||
}
|
||||
/* Connect to the target with a finite amount of retries. */
|
||||
if (result)
|
||||
{
|
||||
for (retryCnt=0; retryCnt<XCPLOADER_CONNECT_RETRIES; retryCnt++)
|
||||
{
|
||||
/* Send the connect command. */
|
||||
if (XcpLoaderSendCmdConnect())
|
||||
{
|
||||
/* Update connection state. */
|
||||
xcpConnected = true;
|
||||
/* Connected so no need to retry. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if a connection with the target could be made within the finite amount
|
||||
* of retries.
|
||||
*/
|
||||
if (!xcpConnected)
|
||||
{
|
||||
/* Disconnect the transport layer again. */
|
||||
xcpSettings.transport->Disconnect();
|
||||
/* Update the result. */
|
||||
result = false;
|
||||
}
|
||||
|
||||
/* Place the target in programming mode if connected. */
|
||||
if (result)
|
||||
{
|
||||
if (!XcpLoaderSendCmdProgramStart())
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderStart ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Stops the firmware update. This is where the bootloader starts the user
|
||||
** program on the target if a valid one is present. After this the connection
|
||||
** with the target is severed.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpLoaderStop(void)
|
||||
{
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer and if actually connected. */
|
||||
if ( (xcpSettings.transport != NULL) && (xcpConnected) ) /*lint !e774 */
|
||||
{
|
||||
/* End the programming session by sending the program command with size 0. */
|
||||
if (XcpLoaderSendCmdProgram(0, NULL))
|
||||
{
|
||||
/* Disconnect the target. Here the reset command is used instead of the disconnect
|
||||
* command, because the bootloader should start the user program on the target.
|
||||
*/
|
||||
(void)XcpLoaderSendCmdProgramReset();
|
||||
}
|
||||
/* Disconnect the transport layer. */
|
||||
xcpSettings.transport->Disconnect();
|
||||
/* Reset connection status. */
|
||||
xcpConnected = false;
|
||||
}
|
||||
} /*** end of XcpLoaderStop ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Requests the bootloader to erase the specified range of memory on the
|
||||
** target. The bootloader aligns this range to hardware specified erase
|
||||
** blocks.
|
||||
** \param address The starting memory address for the erase operation.
|
||||
** \param len The total number of bytes to erase from memory.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderClearMemory(uint32_t address, uint32_t len)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(len > 0);
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue if a transport layer is linked and the parameters are valid. */
|
||||
if ( (len > 0) && (xcpSettings.transport != NULL) && (xcpConnected) )
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* First set the MTA pointer. */
|
||||
if (!XcpLoaderSendCmdSetMta(address))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
/* Now perform the erase operation. */
|
||||
if (result)
|
||||
{
|
||||
if (!XcpLoaderSendCmdProgramClear(len))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderClearMemory ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Requests the bootloader to program the specified data to memory. In case of
|
||||
** non-volatile memory, the application needs to make sure the memory range
|
||||
** was erased beforehand.
|
||||
** \param address The starting memory address for the write operation.
|
||||
** \param len The number of bytes in the data buffer that should be written.
|
||||
** \param data Pointer to the byte array with data to write.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderWriteData(uint32_t address, uint32_t len, uint8_t const * data)
|
||||
{
|
||||
bool result = false;
|
||||
uint8_t currentWriteCnt;
|
||||
uint32_t bufferOffset = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) && (xcpSettings.transport != NULL) && /*lint !e774 */
|
||||
(xcpConnected) )
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* First set the MTA pointer. */
|
||||
if (!XcpLoaderSendCmdSetMta(address))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
/* Perform segmented programming of the data. */
|
||||
if (result)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
/* Set the current write length to make optimal use of the available packet
|
||||
* data.
|
||||
*/
|
||||
currentWriteCnt = len % (xcpMaxProgCto - 1u);
|
||||
if (currentWriteCnt == 0)
|
||||
{
|
||||
currentWriteCnt = (xcpMaxProgCto - 1u);
|
||||
}
|
||||
/* Prepare the packed data for the program command. */
|
||||
if (currentWriteCnt < (xcpMaxProgCto - 1u))
|
||||
{
|
||||
/* Program data. */
|
||||
if (!XcpLoaderSendCmdProgram(currentWriteCnt, &data[bufferOffset]))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Program max data. */
|
||||
if (!XcpLoaderSendCmdProgramMax(&data[bufferOffset]))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Update loop variables. */
|
||||
len -= currentWriteCnt;
|
||||
bufferOffset += currentWriteCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderWriteData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Request the bootloader to upload the specified range of memory. The data is
|
||||
** stored in the data byte array to which the pointer was specified.
|
||||
** \param address The starting memory address for the read operation.
|
||||
** \param len The number of bytes to upload from the target and store in the data
|
||||
** buffer.
|
||||
** \param data Pointer to the byte array where the uploaded data should be stored.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderReadData(uint32_t address, uint32_t len, uint8_t * data)
|
||||
{
|
||||
bool result = false;
|
||||
uint8_t currentReadCnt;
|
||||
uint32_t bufferOffset = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
assert(len > 0);
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (data != NULL) && (len > 0) && (xcpSettings.transport != NULL) && /*lint !e774 */
|
||||
(xcpConnected) )
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* First set the MTA pointer. */
|
||||
if (!XcpLoaderSendCmdSetMta(address))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
/* Perform segmented upload of the data. */
|
||||
if (result)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
/* Set the current read length to make optimal use of the available packet
|
||||
* data.
|
||||
*/
|
||||
currentReadCnt = len % (uint8_t)(xcpMaxDto - 1u);
|
||||
if (currentReadCnt == 0)
|
||||
{
|
||||
currentReadCnt = (uint8_t)(xcpMaxDto - 1u);
|
||||
}
|
||||
/* Upload some data */
|
||||
if (!XcpLoaderSendCmdUpload(&data[bufferOffset], currentReadCnt))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
/* Update loop variables. */
|
||||
len -= currentReadCnt;
|
||||
bufferOffset += currentReadCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderReadData ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Stores a 32-bit value into a byte buffer taking into account Intel
|
||||
** or Motorola byte ordering.
|
||||
** \param value The 32-bit value to store in the buffer.
|
||||
** \param data Array to the buffer for storage.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpLoaderSetOrderedLong(uint32_t value, uint8_t *data)
|
||||
{
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if (data != NULL) /*lint !e774 */
|
||||
{
|
||||
if (xcpSlaveIsIntel)
|
||||
{
|
||||
data[3] = (uint8_t)(value >> 24);
|
||||
data[2] = (uint8_t)(value >> 16);
|
||||
data[1] = (uint8_t)(value >> 8);
|
||||
data[0] = (uint8_t)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
data[0] = (uint8_t)(value >> 24);
|
||||
data[1] = (uint8_t)(value >> 16);
|
||||
data[2] = (uint8_t)(value >> 8);
|
||||
data[3] = (uint8_t)value;
|
||||
}
|
||||
}
|
||||
} /*** end of XcpLoaderSetOrderedLong ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP Connect command.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdConnect(void)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_CONNECT;
|
||||
cmdPacket.data[1] = 0; /* normal mode */
|
||||
cmdPacket.len = 2;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
XCPLOADER_CONNECT_TIMEOUT_MS))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 8) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Process the response data. */
|
||||
if (result)
|
||||
{
|
||||
/* Store slave's byte ordering information. */
|
||||
if ((resPacket.data[2] & 0x01) == 0)
|
||||
{
|
||||
xcpSlaveIsIntel = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
xcpSlaveIsIntel = false;
|
||||
}
|
||||
/* Store max number of bytes the slave allows for master->slave packets. */
|
||||
xcpMaxCto = resPacket.data[3];
|
||||
xcpMaxProgCto = xcpMaxCto;
|
||||
/* Store max number of bytes the slave allows for slave->master packets. */
|
||||
if (xcpSlaveIsIntel)
|
||||
{
|
||||
xcpMaxDto = resPacket.data[4] + (resPacket.data[5] << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
xcpMaxDto = resPacket.data[5] + (resPacket.data[4] << 8);
|
||||
}
|
||||
/* Double check size configuration. CTO length can be adjusted. DTO not. */
|
||||
if (xcpMaxCto > XCPLOADER_PACKET_SIZE_MAX) /*lint !e685 */
|
||||
{
|
||||
xcpMaxCto = XCPLOADER_PACKET_SIZE_MAX;
|
||||
}
|
||||
if (xcpMaxDto > XCPLOADER_PACKET_SIZE_MAX)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
if ( (xcpMaxCto == 0) || (xcpMaxDto == 0) )
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdConnect ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP Set MTA command.
|
||||
** \param address New MTA address for the slave.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdSetMta(uint32_t address)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_SET_MTA;
|
||||
cmdPacket.data[1] = 0; /* Reserved. */
|
||||
cmdPacket.data[2] = 0; /* Reserved. */
|
||||
cmdPacket.data[3] = 0; /* Address extension not supported. */
|
||||
/* Set the address taking into account byte ordering. */
|
||||
XcpLoaderSetOrderedLong(address, &cmdPacket.data[4]);
|
||||
cmdPacket.len = 8;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT1))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 1) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdSetMta ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP UPLOAD command.
|
||||
** \param data Destination data buffer.
|
||||
** \param length Number of bytes to upload.
|
||||
** \return SB_TRUE is successfull, SB_FALSE otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdUpload(uint8_t * data, uint8_t length)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
uint8_t dataIdx;
|
||||
|
||||
/* Cannot request more data then the max rx data - 1. */
|
||||
assert(length < xcpMaxDto);
|
||||
assert(data != NULL);
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer and valid parameters. */
|
||||
if ( (length < xcpMaxDto) && (data != NULL) &&
|
||||
(xcpSettings.transport != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_UPLOAD;
|
||||
cmdPacket.data[1] = length;
|
||||
cmdPacket.len = 2;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT1))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len == 0) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now store the uploaded data. */
|
||||
if (result)
|
||||
{
|
||||
for (dataIdx = 0; dataIdx < length; dataIdx++)
|
||||
{
|
||||
data[dataIdx] = resPacket.data[dataIdx + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdUpload ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP PROGRAM START command.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdProgramStart(void)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_PROGRAM_START;
|
||||
cmdPacket.len = 1;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT3))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 7) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store max number of bytes the slave allows for master->slave packets during the
|
||||
* programming session.
|
||||
*/
|
||||
xcpMaxProgCto = resPacket.data[3];
|
||||
if (xcpMaxProgCto > XCPLOADER_PACKET_SIZE_MAX) /*lint !e685 */
|
||||
{
|
||||
xcpMaxProgCto = XCPLOADER_PACKET_SIZE_MAX;
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdProgramStart ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP PROGRAM RESET command. Note that this command is a bit
|
||||
** different as in it does not require a response.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdProgramReset(void)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_PROGRAM_RESET;
|
||||
cmdPacket.len = 1;
|
||||
/* Send the packet. Note that it is okay if no response is received as this is
|
||||
* allowed for the program reset command. Just make sure to only process the
|
||||
* response if one was actually received.
|
||||
*/
|
||||
if (xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT5))
|
||||
{
|
||||
/* Still here so a response was received. check if the reponse was valid. */
|
||||
if ( (resPacket.len != 1) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdProgramReset ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP PROGRAM command.
|
||||
** \param length Number of bytes in the data array to program.
|
||||
** \param data Array with data bytes to program.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdProgram(uint8_t length, uint8_t const * data)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
uint8_t cnt;
|
||||
|
||||
/* Verify that this number of bytes actually fits in this command. */
|
||||
assert((length <= (xcpMaxProgCto-2)) &&
|
||||
(xcpMaxProgCto <= XCPLOADER_PACKET_SIZE_MAX)); /*lint !e685 */
|
||||
if (length > 0)
|
||||
{
|
||||
assert(data != NULL);
|
||||
}
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer and valid parameters. */
|
||||
if ( (length <= (xcpMaxProgCto-2)) &&
|
||||
(xcpMaxProgCto <= XCPLOADER_PACKET_SIZE_MAX) && /*lint !e685 */
|
||||
(xcpSettings.transport != NULL) )/*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_PROGRAM;
|
||||
cmdPacket.data[1] = length;
|
||||
/* Only access data if it is not a NULL pointer. */
|
||||
if (data != NULL)
|
||||
{
|
||||
for (cnt=0; cnt<length; cnt++)
|
||||
{
|
||||
cmdPacket.data[cnt+2] = data[cnt];
|
||||
}
|
||||
}
|
||||
cmdPacket.len = length + 2;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT5))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 1) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdProgram ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP PROGRAM MAX command.
|
||||
** \param data Array with data bytes to program.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdProgramMax(uint8_t const * data)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
uint8_t cnt;
|
||||
|
||||
/* verify that this number of bytes actually fits in this command */
|
||||
assert(xcpMaxProgCto <= XCPLOADER_PACKET_SIZE_MAX); /*lint !e685 */
|
||||
assert(data != NULL);
|
||||
/* Only continue with a valid transport layer and valid parameters. */
|
||||
if ( (xcpMaxProgCto <= XCPLOADER_PACKET_SIZE_MAX) && (data != NULL) && /*lint !e685 */
|
||||
(xcpSettings.transport != NULL) )/*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_PROGRAM_MAX;
|
||||
for (cnt = 0; cnt < (xcpMaxProgCto-1); cnt++)
|
||||
{
|
||||
cmdPacket.data[cnt+1] = data[cnt];
|
||||
}
|
||||
cmdPacket.len = xcpMaxProgCto;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT5))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 1) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdProgramMax ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP PROGRAM CLEAR command.
|
||||
** \param length Number of elements to clear starting at the MTA address.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdProgramClear(uint32_t length)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/*Pprepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_PROGRAM_CLEAR;
|
||||
cmdPacket.data[1] = 0; /* Use absolute mode. */
|
||||
cmdPacket.data[2] = 0; /* Reserved. */
|
||||
cmdPacket.data[3] = 0; /* Reserved. */
|
||||
/* Set the erase length taking into account byte ordering. */
|
||||
XcpLoaderSetOrderedLong(length, &cmdPacket.data[4]);
|
||||
cmdPacket.len = 8;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT4))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 1) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdProgramClear ***/
|
||||
|
||||
|
||||
/*********************************** end of xcploader.c ********************************/
|
|
@ -0,0 +1,112 @@
|
|||
/************************************************************************************//**
|
||||
* \file xcploader.h
|
||||
* \brief XCP Loader module header file.
|
||||
* \ingroup XcpLoader
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
/************************************************************************************//**
|
||||
* \defgroup XcpLoader XCP version 1.0 protocol
|
||||
* \brief This module implements the XCP communication protocol that can be linked
|
||||
* to the Session module.
|
||||
* \ingroup Session
|
||||
* \details
|
||||
* This XCP Loader module contains functionality according to the standardized XCP
|
||||
* protocol version 1.0. XCP is a universal measurement and calibration communication
|
||||
* protocol. Note that only those parts of the XCP master functionality are implemented
|
||||
* that are applicable to performing a firmware update on the slave. This means
|
||||
* functionality for reading, programming, and erasing (non-volatile) memory.
|
||||
****************************************************************************************/
|
||||
#ifndef XCPLOADER_H
|
||||
#define XCPLOADER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Total number of bytes in a master<->slave data packet. It should be at least
|
||||
* equal or larger than that configured on the slave.
|
||||
*/
|
||||
#define XCPLOADER_PACKET_SIZE_MAX (255u)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/** \brief XCP transport layer packet type. */
|
||||
typedef struct t_xcp_transport_packet
|
||||
{
|
||||
uint8_t data[XCPLOADER_PACKET_SIZE_MAX]; /**< Packet data. */
|
||||
uint8_t len; /**< Packet length. */
|
||||
} tXcpTransportPacket;
|
||||
|
||||
/** \brief XCP transport layer. */
|
||||
typedef struct t_xcp_transport
|
||||
{
|
||||
/** \brief Initialization of the XCP transpor layer. */
|
||||
void (*Init) (void const * settings);
|
||||
/** \brief Termination the XCP transpor layer. */
|
||||
void (*Terminate) (void);
|
||||
/** \brief Connects the XCP transpor layer. */
|
||||
bool (*Connect) (void);
|
||||
/** \brief Disconnects the XCP transpor layer. */
|
||||
void (*Disconnect) (void);
|
||||
/** \brief Sends an XCP packet and waits for the response to come back. */
|
||||
bool (*SendPacket) (tXcpTransportPacket const * txPacket,
|
||||
tXcpTransportPacket * rxPacket, uint16_t timeout);
|
||||
} tXcpTransport;
|
||||
|
||||
/** \brief XCP protocol specific settings. */
|
||||
typedef struct t_xcp_loader_settings
|
||||
{
|
||||
/** \brief Command response timeout in milliseconds. */
|
||||
uint16_t timeoutT1;
|
||||
/** \brief Start programming timeout in milliseconds. */
|
||||
uint16_t timeoutT3;
|
||||
/** \brief Erase memory timeout in milliseonds. */
|
||||
uint16_t timeoutT4;
|
||||
/** \brief Program memory and reset timeout in milliseonds. */
|
||||
uint16_t timeoutT5;
|
||||
/** \brief Busy wait timer timeout in milliseonds. */
|
||||
uint16_t timeoutT7;
|
||||
/** \brief Pointer to the transport layer to use during protocol communications. */
|
||||
tXcpTransport const * transport;
|
||||
/** \brief Pointer to the settings for the transport layer. */
|
||||
void const * transportSettings;
|
||||
} tXcpLoaderSettings;
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
tSessionProtocol const * XcpLoaderGetProtocol(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XCPLOADER_H */
|
||||
/*********************************** end of xcploader.h ********************************/
|
|
@ -0,0 +1,329 @@
|
|||
/************************************************************************************//**
|
||||
* \file xcptpuart.c
|
||||
* \brief XCP UART transport layer source file.
|
||||
* \ingroup XcpLoader
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <stdlib.h> /* for standard library */
|
||||
#include <string.h> /* for string library */
|
||||
#include "session.h" /* Communication session module */
|
||||
#include "xcploader.h" /* XCP loader module */
|
||||
#include "xcptpuart.h" /* XCP UART transport layer */
|
||||
#include "util.h" /* Utility module */
|
||||
#include "serialport.h" /* Serial port module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
static void XcpTpUartInit(void const * settings);
|
||||
static void XcpTpUartTerminate(void);
|
||||
static bool XcpTpUartConnect(void);
|
||||
static void XcpTpUartDisconnect(void);
|
||||
static bool XcpTpUartSendPacket(tXcpTransportPacket const * txPacket,
|
||||
tXcpTransportPacket * rxPacket, uint16_t timeout);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local constant declarations
|
||||
****************************************************************************************/
|
||||
/** \brief XCP transport layer structure filled with UART specifics. */
|
||||
static const tXcpTransport uartTransport =
|
||||
{
|
||||
XcpTpUartInit,
|
||||
XcpTpUartTerminate,
|
||||
XcpTpUartConnect,
|
||||
XcpTpUartDisconnect,
|
||||
XcpTpUartSendPacket
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief The settings to use in this transport layer. */
|
||||
static tXcpTpUartSettings tpUartSettings;
|
||||
|
||||
|
||||
/***********************************************************************************//**
|
||||
** \brief Obtains a pointer to the transport layer structure, so that it can be
|
||||
** linked to the XCP protocol module.
|
||||
** \return Pointer to transport layer structure.
|
||||
**
|
||||
****************************************************************************************/
|
||||
tXcpTransport const * XcpTpUartGetTransport(void)
|
||||
{
|
||||
return &uartTransport;
|
||||
} /*** end of XcpLoaderGetProtocol ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the transport layer.
|
||||
** \param settings Pointer to settings structure.
|
||||
** \return None.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpTpUartInit(void const * settings)
|
||||
{
|
||||
char * uartPortName;
|
||||
|
||||
/* Reset transport layer settings. */
|
||||
tpUartSettings.portname = NULL;
|
||||
tpUartSettings.baudrate = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(settings != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if (settings != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Shallow copy the transport layer settings for layer usage. */
|
||||
tpUartSettings = *((tXcpTpUartSettings *)settings);
|
||||
/* The portname is a pointer and it is not gauranteed that it stays valid so we need
|
||||
* to deep copy this one. note the +1 for '\0' in malloc.
|
||||
*/
|
||||
assert(((tXcpTpUartSettings *)settings)->portname != NULL);
|
||||
if (((tXcpTpUartSettings *)settings)->portname != NULL) /*lint !e774 */
|
||||
{
|
||||
uartPortName = malloc(strlen(((tXcpTpUartSettings *)settings)->portname) + 1);
|
||||
assert(uartPortName != NULL);
|
||||
if (uartPortName != NULL) /*lint !e774 */
|
||||
{
|
||||
strcpy(uartPortName, ((tXcpTpUartSettings *)settings)->portname);
|
||||
tpUartSettings.portname = uartPortName;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Initialize the serial port. */
|
||||
SerialPortInit();
|
||||
} /*** end of XcpTpUartInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the transport layer.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpTpUartTerminate(void)
|
||||
{
|
||||
/* Terminate the serial port. */
|
||||
SerialPortTerminate();
|
||||
/* Release memory that was allocated for storing the port name. */
|
||||
if (tpUartSettings.portname != NULL)
|
||||
{
|
||||
free((char *)tpUartSettings.portname);
|
||||
}
|
||||
/* Reset transport layer settings. */
|
||||
tpUartSettings.portname = NULL;
|
||||
tpUartSettings.baudrate = 0;
|
||||
} /*** end of XcpTpUartTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Connects to the transport layer.
|
||||
** \return True is connected, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpTpUartConnect(void)
|
||||
{
|
||||
bool result = false;
|
||||
bool baudrateSupported;
|
||||
tSerialPortBaudrate baudrate;
|
||||
|
||||
/* Check if the specified baudrate is supported by the serial port driver. */
|
||||
baudrateSupported = (tpUartSettings.baudrate == 9600) ||
|
||||
(tpUartSettings.baudrate == 19200) ||
|
||||
(tpUartSettings.baudrate == 38400) ||
|
||||
(tpUartSettings.baudrate == 57600) ||
|
||||
(tpUartSettings.baudrate == 115200);
|
||||
|
||||
/* Check transport layer settings. */
|
||||
assert(tpUartSettings.portname != NULL);
|
||||
assert(baudrateSupported);
|
||||
|
||||
/* Only continue if the transport layer settings are valid. */
|
||||
if ( (tpUartSettings.portname != NULL) && (baudrateSupported) ) /*lint !e774 */
|
||||
{
|
||||
/* Convert the numeric baudrate to the one supported by the serial port driver. */
|
||||
switch (tpUartSettings.baudrate)
|
||||
{
|
||||
case 115200:
|
||||
baudrate = SERIALPORT_BR115200;
|
||||
break;
|
||||
case 57600:
|
||||
baudrate = SERIALPORT_BR57600;
|
||||
break;
|
||||
case 38400:
|
||||
baudrate = SERIALPORT_BR38400;
|
||||
break;
|
||||
case 19200:
|
||||
baudrate = SERIALPORT_BR19200;
|
||||
break;
|
||||
case 9600:
|
||||
default:
|
||||
baudrate = SERIALPORT_BR9600;
|
||||
break;
|
||||
}
|
||||
/* Connect to the serial port. */
|
||||
result = SerialPortOpen(tpUartSettings.portname, baudrate);
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpTpUartConnect ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Disconnects from the transport layer.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpTpUartDisconnect(void)
|
||||
{
|
||||
/* Disconnect from the serial port. */
|
||||
SerialPortClose();
|
||||
} /*** end of XcpTpUartDisconnect ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Transmits an XCP packet on the transport layer and attempts to receive the
|
||||
** response packet within the specified timeout.
|
||||
** \param txPacket Pointer to the packet to transmit.
|
||||
** \param rxPacket Pointer where the received packet info is stored.
|
||||
** \param timeout Maximum time in milliseconds to wait for the reception of the
|
||||
** response packet.
|
||||
** \return True is successful and a response packet was received, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpTpUartSendPacket(tXcpTransportPacket const * txPacket,
|
||||
tXcpTransportPacket * rxPacket, uint16_t timeout)
|
||||
{
|
||||
bool result = false;
|
||||
uint16_t byteIdx;
|
||||
/* uartBuffer is static to lower the stack load. +1 because the first byte for an XCP
|
||||
* packet on the UART transport layer contains the packet lenght.
|
||||
*/
|
||||
static uint8_t uartBuffer[XCPLOADER_PACKET_SIZE_MAX + 1];
|
||||
uint32_t responseTimeoutTime = 0;
|
||||
bool packetReceptionComplete;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(txPacket != NULL);
|
||||
assert(rxPacket != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if ( (txPacket != NULL) && (rxPacket != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Set result value to okay and only change it from now on if an error occurred. */
|
||||
result = true;
|
||||
/* Prepare the XCP packet for transmission on UART. This is basically the same as
|
||||
* the XCP packet data but just the length of the packet is added to the first
|
||||
* byte.
|
||||
*/
|
||||
uartBuffer[0] = txPacket->len;
|
||||
for (byteIdx=0; byteIdx<txPacket->len; byteIdx++)
|
||||
{
|
||||
uartBuffer[byteIdx + 1] = txPacket->data[byteIdx];
|
||||
}
|
||||
/* Transmit the packet. */
|
||||
if (!SerialPortWrite(uartBuffer, txPacket->len + 1))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
/* Only continue if the transmission was successful. */
|
||||
if (result)
|
||||
{
|
||||
/* Determine timeout time for the response packet. */
|
||||
responseTimeoutTime = UtilTimeGetSystemTimeMs() + timeout;
|
||||
/* Initialize packet reception length. */
|
||||
rxPacket->len = 0;
|
||||
/* Poll with timeout detection to receive the first byte. This one contains the
|
||||
* packet length and cannot be zero.
|
||||
*/
|
||||
while (UtilTimeGetSystemTimeMs() < responseTimeoutTime)
|
||||
{
|
||||
if (SerialPortRead(&rxPacket->len, 1))
|
||||
{
|
||||
/* Length received. Validate it before accepting it */
|
||||
if (rxPacket->len > 0)
|
||||
{
|
||||
/* Start of packet received. Stop this loop to continue with the
|
||||
* reception of the packet.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if a valid start of packet was received, in which case the first
|
||||
* byte won't have a zero value.
|
||||
*/
|
||||
if (rxPacket->len == 0)
|
||||
{
|
||||
/* No valid start of packet received, so a timeout occurred. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only continue with reception if a valid pacekt lenght was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Continue with reception of the packet. */
|
||||
packetReceptionComplete = false;
|
||||
byteIdx = 0;
|
||||
/* Poll with timeout detection to receive the full packet. */
|
||||
while (UtilTimeGetSystemTimeMs() < responseTimeoutTime)
|
||||
{
|
||||
/* Check if the next byte was received. */
|
||||
if (SerialPortRead(&rxPacket->data[byteIdx], 1))
|
||||
{
|
||||
/* Check if the packet reception is now complete. */
|
||||
if ((byteIdx + 1) == rxPacket->len)
|
||||
{
|
||||
/* Set flag and stop the loop. */
|
||||
packetReceptionComplete = true;
|
||||
break;
|
||||
}
|
||||
/* Increment indexer to the next byte. */
|
||||
byteIdx++;
|
||||
}
|
||||
}
|
||||
/* Check if a timeout occurred. */
|
||||
if (!packetReceptionComplete)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpTpUartSendPacket ***/
|
||||
|
||||
|
||||
/*********************************** end of xcptpuart.c ********************************/
|
|
@ -0,0 +1,58 @@
|
|||
/************************************************************************************//**
|
||||
* \file xcptpuart.h
|
||||
* \brief XCP UART transport layer header file.
|
||||
* \ingroup XcpLoader
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
#ifndef XCPTPUART_H
|
||||
#define XCPTPUART_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/** \brief Layout of structure with settings specific to the XCP transport layer module
|
||||
* for UART.
|
||||
*/
|
||||
typedef struct t_xcp_tp_uart_settings
|
||||
{
|
||||
char const * portname; /**< Interface port name, i.e. /dev/ttyUSB0. */
|
||||
uint32_t baudrate; /**< Communication speed in bits/sec. */
|
||||
} tXcpTpUartSettings;
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
tXcpTransport const * XcpTpUartGetTransport(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XCPTPUART_H */
|
||||
/*********************************** end of xcptpuart.h ********************************/
|
Loading…
Reference in New Issue