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