diff --git a/CMakeLists.txt b/CMakeLists.txt index 0538f3b14..52f6867f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + ### # General project settings ### @@ -48,29 +49,34 @@ endif () find_package(libusb REQUIRED) ## Check for system-specific additional header files and libraries + include(CheckIncludeFile) +include(CheckLibraryExists) + +CHECK_LIBRARY_EXISTS(ssp __stack_chk_fail "" _stack_chk_fail_exists) +if (_stack_chk_fail_exists) + if (WIN32) + set(SSP_LIB -static ssp) + else () + set(SSP_LIB ssp) + endif () +else () + set(SSP_LIB "") +endif () CHECK_INCLUDE_FILE(sys/mman.h STLINK_HAVE_SYS_MMAN_H) if (STLINK_HAVE_SYS_MMAN_H) add_definitions(-DSTLINK_HAVE_SYS_MMAN_H) -endif () +endif() CHECK_INCLUDE_FILE(unistd.h STLINK_HAVE_UNISTD_H) if (STLINK_HAVE_UNISTD_H) add_definitions(-DSTLINK_HAVE_UNISTD_H) endif () -include(CheckLibraryExists) - -CHECK_LIBRARY_EXISTS(ssp __stack_chk_fail "" _stack_chk_fail_exists) -if (_stack_chk_fail_exists) - if(WIN32) - set(SSP_LIB -static ssp) - else() - set(SSP_LIB ssp) - endif() -else () - set(SSP_LIB "") +if (MSVC) + # Use string.h rather than strings.h and disable annoying warnings + add_definitions(-DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS /wd4710) endif () @@ -81,50 +87,53 @@ endif () ## Define include directories to avoid absolute paths for header defines include_directories(${LIBUSB_INCLUDE_DIR}) -# ==== -include_directories(${PROJECT_SOURCE_DIR}/include) ### TODO: Clean this up... -include_directories(${PROJECT_BINARY_DIR}/include/stlink) -include_directories(${PROJECT_SOURCE_DIR}/include/stlink) -include_directories(${PROJECT_SOURCE_DIR}/include/stlink/tools) -# ==== +include_directories(${PROJECT_SOURCE_DIR}/inc) # contains top-level header files +include_directories(${PROJECT_BINARY_DIR}/inc) # contains version.h include_directories(src) -include_directories(src/tools) ### TODO: Clean this up... +include_directories(src/st-flash) +include_directories(src/stlink-lib) set(STLINK_HEADERS - include/stlink.h - include/stlink/backend.h - include/stlink/chipid.h - include/stlink/commands.h - include/stlink/flash_loader.h - include/stlink/reg.h - src/logging.h - src/md5.h - src/sg.h - src/usb.h + inc/backend.h + src/stlink-lib/commands.h + src/stlink-lib/libusb_settings.h + src/stlink-lib/reg.h + inc/stlink.h + src/stlink-lib/chipid.h + src/stlink-lib/flash_loader.h + src/stlink-lib/logging.h + src/stlink-lib/md5.h + src/stlink-lib/sg.h + src/stlink-lib/usb.h ) set(STLINK_SOURCE src/common.c - src/chipid.c - src/flash_loader.c - src/logging.c - src/md5.c - src/sg.c - src/usb.c + src/stlink-lib/chipid.c + src/stlink-lib/flash_loader.c + src/stlink-lib/logging.c + src/stlink-lib/md5.c + src/stlink-lib/sg.c + src/stlink-lib/usb.c ) -if (WIN32 OR MINGW OR MSYS) - include_directories(src/mingw) - set(STLINK_SOURCE "${STLINK_SOURCE};src/mmap.c;src/mingw/mingw.c") - set(STLINK_HEADERS "${STLINK_HEADERS};src/mmap.h;src/mingw/mingw.h") -endif () - -if (MSVC) +if (WIN32) include_directories(src/win32) - include_directories(src/getopt) - # Use string.h rather than strings.h and disable annoying warnings - add_definitions(-DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS /wd4710) + set(STLINK_SOURCE "${STLINK_SOURCE};src/win32/win32_socket.c") + set(STLINK_HEADERS "${STLINK_HEADERS};src/win32/win32_socket.h") + + if (MSVC) + # Add drop-in replacement for unistd.h to sources + include_directories(src/win32/unistd) + set(STLINK_HEADERS "${STLINK_HEADERS};src/win32/unistd/unistd.h") + endif () + + if (NOT STLINK_HAVE_SYS_MMAN_H) + include_directories(src/win32/mmap) + set(STLINK_SOURCE "${STLINK_SOURCE};src/win32/mmap.c") + set(STLINK_HEADERS "${STLINK_HEADERS};src/win32/mmap.h") + endif() endif () ## Include test execution for test-targets for target Debug @@ -140,7 +149,7 @@ endif () set(STLINK_LIBRARY_PATH ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Main library install directory") # Set the environment variable LD_LIBRARY_PATH to point to /usr/local/lib (per default). -execute_process (COMMAND bash -c "export LD_LIBRARY_PATH="${CMAKE_INSTALL_LIBDIR}" ") +execute_process (COMMAND bash -c "export LD_LIBRARY_PATH=${CMAKE_INSTALL_LIBDIR}") ### @@ -221,15 +230,18 @@ install(TARGETS ${STLINK_LIB_STATIC} ARCHIVE DESTINATION ${STLINK_LIBRARY_PATH}) # Build toolset executables ### +set(ST-FLASH_SOURCES src/st-flash/flash.c src/st-flash/flash_opts.c) +set(ST-INFO_SOURCES src/st-info/info.c) set(ST-UTIL_SOURCES src/st-util/gdb-remote.c src/st-util/gdb-server.c src/st-util/semihosting.c) if (MSVC) # Add getopt to sources - set(ST-UTIL_SOURCES "${ST-UTIL_SOURCES};src/getopt/getopt.c") + include_directories(src/win32/getopt) + set(ST-UTIL_SOURCES "${ST-UTIL_SOURCES};src/win32/getopt/getopt.c") endif () -add_executable(st-flash src/tools/flash.c src/tools/flash_opts.c) -add_executable(st-info src/tools/info.c) +add_executable(st-flash ${ST-FLASH_SOURCES}) +add_executable(st-info ${ST-INFO_SOURCES}) add_executable(st-util ${ST-UTIL_SOURCES}) if (WIN32 OR APPLE) @@ -267,11 +279,7 @@ endif () # Additional build tasks ### -# ==== -add_subdirectory(include) # contains subordinate CMakeLists for version config and old header includes - ### TODO: Clean this up ... -# ==== - +add_subdirectory(inc) # contains subordinate CMakeLists for version config add_subdirectory(src/stlink-gui) # contains subordinate CMakeLists to build GUI add_subdirectory(tests) # contains subordinate CMakeLists to build test executables add_subdirectory(cmake/packaging) # contains subordinate CMakeLists to build packages diff --git a/cmake/modules/c_flags.cmake b/cmake/modules/c_flags.cmake index 520182e37..8291ea0ee 100644 --- a/cmake/modules/c_flags.cmake +++ b/cmake/modules/c_flags.cmake @@ -18,6 +18,7 @@ function(add_cflag_if_supported flag) endfunction() add_cflag_if_supported("-std=gnu11") +add_cflag_if_supported("-std=gnu18") add_cflag_if_supported("-Wall") add_cflag_if_supported("-Wextra") add_cflag_if_supported("-Wshadow") diff --git a/config/code_style.cfg b/config/code_style.cfg new file mode 100644 index 000000000..c6ced268c --- /dev/null +++ b/config/code_style.cfg @@ -0,0 +1,3090 @@ +# Uncrustify-0.71.0 + +# +# General options +# + +# The type of line endings. +# +# Default: auto +newlines = auto # lf/crlf/cr/auto + +# The original size of tabs in the input. +# +# Default: 8 +input_tab_size = 4 # unsigned number + +# The size of tabs in the output (only used if align_with_tabs=true). +# +# Default: 8 +output_tab_size = 4 # unsigned number + +# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). +# +# Default: 92 +string_escape_char = 92 # unsigned number + +# Alternate string escape char (usually only used for Pawn). +# Only works right before the quote char. +string_escape_char2 = 0 # unsigned number + +# Replace tab characters found in string literals with the escape sequence \t +# instead. +string_replace_tab_chars = false # true/false + +# Allow interpreting '>=' and '>>=' as part of a template in code like +# 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. +# Improvements to template detection may make this option obsolete. +tok_split_gte = false # true/false + +# Disable formatting of NL_CONT ('\\n') ended lines (e.g. multiline macros) +#disable_processing_nl_cont = false # true/false ### not 0.69 + +# Specify the marker used in comments to disable processing of part of the +# file. +# The comment should be used alone in one line. +# +# Default: *INDENT-OFF* +disable_processing_cmt = " *INDENT-OFF*" # string + +# Specify the marker used in comments to (re)enable processing in a file. +# The comment should be used alone in one line. +# +# Default: *INDENT-ON* +enable_processing_cmt = " *INDENT-ON*" # string + +# Enable parsing of digraphs. +enable_digraphs = false # true/false + +# Add or remove the UTF-8 BOM (recommend 'remove'). +utf8_bom = ignore # ignore/add/remove/force + +# If the file contains bytes with values between 128 and 255, but is not +# UTF-8, then output as UTF-8. +utf8_byte = false # true/false + +# Force the output encoding to UTF-8. +utf8_force = true # true/false + +# Add or remove space between 'do' and '{'. +#sp_do_brace_open = add # ignore/add/remove/force ### not 0.69 + +# Add or remove space between '}' and 'while'. +#sp_brace_close_while = add # ignore/add/remove/force ### not 0.69 + +# Add or remove space between 'while' and '('. +#sp_while_paren_open = add # ignore/add/remove/force ### not 0.69 + +# +# Spacing options +# + +# Add or remove space around non-assignment symbolic operators ('+', '/', '%', +# '<<', and so forth). +sp_arith = add # ignore/add/remove/force + +# Add or remove space around arithmetic operators '+' and '-'. +# +# Overrides sp_arith. +sp_arith_additive = add # ignore/add/remove/force + +# Add or remove space around assignment operator '=', '+=', etc. +sp_assign = add # ignore/add/remove/force + +# Add or remove space around '=' in C++11 lambda capture specifications. +# +# Overrides sp_assign. +sp_cpp_lambda_assign = add # ignore/add/remove/force + +# Add or remove space after the capture specification of a C++11 lambda when +# an argument list is present, as in '[] (int x){ ... }'. +#sp_cpp_lambda_square_paren = add # ignore/add/remove/force ### not 0.69 + +# Add or remove space after the capture specification of a C++11 lambda with +# no argument list is present, as in '[] { ... }'. +#sp_cpp_lambda_square_brace = add # ignore/add/remove/force ### not 0.69 + +# Add or remove space after the argument list of a C++11 lambda, as in +# '[](int x) { ... }'. +#sp_cpp_lambda_paren_brace = add # ignore/add/remove/force ### not 0.69 + +# Add or remove space between a lambda body and its call operator of an +# immediately invoked lambda, as in '[]( ... ){ ... } ( ... )'. +#sp_cpp_lambda_fparen = add # ignore/add/remove/force ### not 0.69 + +# Add or remove space around assignment operator '=' in a prototype. +# +# If set to ignore, use sp_assign. +sp_assign_default = add # ignore/add/remove/force + +# Add or remove space before assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_before_assign = add # ignore/add/remove/force + +# Add or remove space after assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_after_assign = add # ignore/add/remove/force + +# Add or remove space in 'NS_ENUM ('. +sp_enum_paren = add # ignore/add/remove/force + +# Add or remove space around assignment '=' in enum. +sp_enum_assign = add # ignore/add/remove/force + +# Add or remove space before assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_before_assign = add # ignore/add/remove/force + +# Add or remove space after assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_after_assign = add # ignore/add/remove/force + +# Add or remove space around assignment ':' in enum. +sp_enum_colon = add # ignore/add/remove/force + +# Add or remove space around preprocessor '##' concatenation operator. +# +# Default: add +sp_pp_concat = add # ignore/add/remove/force + +# Add or remove space after preprocessor '#' stringify operator. +# Also affects the '#@' charizing operator. +sp_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space before preprocessor '#' stringify operator +# as in '#define x(y) L#y'. +sp_before_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space around boolean operators '&&' and '||'. +sp_bool = add # ignore/add/remove/force + +# Add or remove space around compare operator '<', '>', '==', etc. +sp_compare = add # ignore/add/remove/force + +# Add or remove space inside '(' and ')'. +sp_inside_paren = remove # ignore/add/remove/force + +# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. +sp_paren_paren = remove # ignore/add/remove/force + +# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. +sp_cparen_oparen = add # ignore/add/remove/force + +# Whether to balance spaces inside nested parentheses. +sp_balance_nested_parens = false # true/false + +# Add or remove space between ')' and '{'. +sp_paren_brace = add # ignore/add/remove/force + +# Add or remove space between nested braces, i.e. '{{' vs '{ {'. +sp_brace_brace = remove # ignore/add/remove/force + +# Add or remove space before pointer star '*'. +sp_before_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space before pointer star '*' that isn't followed by a +# variable name. If set to ignore, sp_before_ptr_star is used instead. +sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space between pointer stars '*'. +sp_between_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a word. +# +# Overrides sp_type_func. +sp_after_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space after pointer caret '^', if followed by a word. +sp_after_ptr_block_caret = ignore # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a qualifier. +sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_ptr_star and sp_type_func. +sp_after_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by an open +# parenthesis, as in 'void* (*)(). +sp_ptr_star_paren = ignore # ignore/add/remove/force + +# Add or remove space before a pointer star '*', if followed by a function +# prototype or function definition. +sp_before_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&'. +sp_before_byref = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&' that isn't followed by a +# variable name. If set to ignore, sp_before_byref is used instead. +sp_before_unnamed_byref = ignore # ignore/add/remove/force + +# Add or remove space after reference sign '&', if followed by a word. +# +# Overrides sp_type_func. +sp_after_byref = ignore # ignore/add/remove/force + +# Add or remove space after a reference sign '&', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_byref and sp_type_func. +sp_after_byref_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&', if followed by a function +# prototype or function definition. +sp_before_byref_func = ignore # ignore/add/remove/force + +# Add or remove space between type and word. +# +# Default: force +sp_after_type = force # ignore/add/remove/force + +# Add or remove space between 'decltype(...)' and word. +sp_after_decltype = ignore # ignore/add/remove/force + +# (D) Add or remove space before the parenthesis in the D constructs +# 'template Foo(' and 'class Foo('. +sp_before_template_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'template' and '<'. +# If set to ignore, sp_before_angle is used. +sp_template_angle = ignore # ignore/add/remove/force + +# Add or remove space before '<'. +sp_before_angle = ignore # ignore/add/remove/force + +# Add or remove space inside '<' and '>'. +sp_inside_angle = ignore # ignore/add/remove/force + +# Add or remove space inside '<>'. +sp_inside_angle_empty = add # ignore/add/remove/force + +# Add or remove space between '>' and ':'. +sp_angle_colon = ignore # ignore/add/remove/force + +# Add or remove space after '>'. +sp_after_angle = ignore # ignore/add/remove/force + +# Add or remove space between '>' and '(' as found in 'new List(foo);'. +sp_angle_paren = remove # ignore/add/remove/force + +# Add or remove space between '>' and '()' as found in 'new List();'. +sp_angle_paren_empty = remove # ignore/add/remove/force + +# Add or remove space between '>' and a word as in 'List m;' or +# 'template static ...'. +sp_angle_word = add # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff). +# +# Default: add +sp_angle_shift = add # ignore/add/remove/force + +# (C++11) Permit removal of the space between '>>' in 'foo >'. Note +# that sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = false # true/false + +# Add or remove space before '(' of control statements ('if', 'for', 'switch', +# 'while', etc.). +sp_before_sparen = add # ignore/add/remove/force + +# Add or remove space inside '(' and ')' of control statements. +sp_inside_sparen = ignore # ignore/add/remove/force + +# Add or remove space after '(' of control statements. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_open = ignore # ignore/add/remove/force + +# Add or remove space before ')' of control statements. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_close = ignore # ignore/add/remove/force + +# Add or remove space after ')' of control statements. +sp_after_sparen = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of of control statements. +sp_sparen_brace = add # ignore/add/remove/force + +# (D) Add or remove space between 'invariant' and '('. +sp_invariant_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space after the ')' in 'invariant (C) c'. +sp_after_invariant_paren = ignore # ignore/add/remove/force + +# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. +sp_special_semi = add # ignore/add/remove/force + +# Add or remove space before ';'. +# +# Default: remove +sp_before_semi = remove # ignore/add/remove/force + +# Add or remove space before ';' in non-empty 'for' statements. +sp_before_semi_for = remove # ignore/add/remove/force + +# Add or remove space before a semicolon of an empty part of a for statement. +sp_before_semi_for_empty = add # ignore/add/remove/force + +# Add or remove space after ';', except when followed by a comment. +# +# Default: add +sp_after_semi = add # ignore/add/remove/force + +# Add or remove space after ';' in non-empty 'for' statements. +# +# Default: force +sp_after_semi_for = force # ignore/add/remove/force + +# Add or remove space after the final semicolon of an empty part of a for +# statement, as in 'for ( ; ; )'. +sp_after_semi_for_empty = ignore # ignore/add/remove/force + +# Add or remove space before '[' (except '[]'). +sp_before_square = ignore # ignore/add/remove/force + +# Add or remove space before '[' for a variable definition. +# +# Default: remove +#sp_before_vardef_square = remove # ignore/add/remove/force ### not 0.69 + +# Add or remove space before '[' for asm block. +#sp_before_square_asm_block = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove space before '[]'. +sp_before_squares = ignore # ignore/add/remove/force + +# Add or remove space before C++17 structured bindings. +sp_cpp_before_struct_binding = ignore # ignore/add/remove/force + +# Add or remove space inside a non-empty '[' and ']'. +sp_inside_square = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and +# ']'. If set to ignore, sp_inside_square is used. +sp_inside_square_oc_array = ignore # ignore/add/remove/force + +# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. +sp_after_comma = add # ignore/add/remove/force + +# Add or remove space before ','. +# +# Default: remove +sp_before_comma = remove # ignore/add/remove/force + +# (C#) Add or remove space between ',' and ']' in multidimensional array type +# like 'int[,,]'. +sp_after_mdatype_commas = ignore # ignore/add/remove/force + +# (C#) Add or remove space between '[' and ',' in multidimensional array type +# like 'int[,,]'. +sp_before_mdatype_commas = ignore # ignore/add/remove/force + +# (C#) Add or remove space between ',' in multidimensional array type +# like 'int[,,]'. +sp_between_mdatype_commas = ignore # ignore/add/remove/force + +# Add or remove space between an open parenthesis and comma, +# i.e. '(,' vs. '( ,'. +# +# Default: force +sp_paren_comma = force # ignore/add/remove/force + +# Add or remove space before the variadic '...' when preceded by a +# non-punctuator. +sp_before_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between a type and '...'. +sp_type_ellipsis = ignore # ignore/add/remove/force + +# (D) Add or remove space between a type and '?'. +sp_type_question = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '...'. +sp_paren_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between ')' and a qualifier such as 'const'. +sp_paren_qualifier = ignore # ignore/add/remove/force + +# Add or remove space between ')' and 'noexcept'. +sp_paren_noexcept = ignore # ignore/add/remove/force + +# Add or remove space after class ':'. +sp_after_class_colon = ignore # ignore/add/remove/force + +# Add or remove space before class ':'. +sp_before_class_colon = ignore # ignore/add/remove/force + +# Add or remove space after class constructor ':'. +sp_after_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before class constructor ':'. +sp_before_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before case ':'. +# +# Default: remove +sp_before_case_colon = remove # ignore/add/remove/force + +# Add or remove space between 'operator' and operator sign. +sp_after_operator = ignore # ignore/add/remove/force + +# Add or remove space between the operator symbol and the open parenthesis, as +# in 'operator ++('. +sp_after_operator_sym = ignore # ignore/add/remove/force + +# Overrides sp_after_operator_sym when the operator has no arguments, as in +# 'operator *()'. +sp_after_operator_sym_empty = ignore # ignore/add/remove/force + +# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or +# '(int)a' vs. '(int) a'. +sp_after_cast = remove # ignore/add/remove/force + +# Add or remove spaces inside cast parentheses. +sp_inside_paren_cast = ignore # ignore/add/remove/force + +# Add or remove space between the type and open parenthesis in a C++ cast, +# i.e. 'int(exp)' vs. 'int (exp)'. +sp_cpp_cast_paren = remove # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '('. +sp_sizeof_paren = remove # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '...'. +sp_sizeof_ellipsis = add # ignore/add/remove/force + +# Add or remove space between 'sizeof...' and '('. +sp_sizeof_ellipsis_paren = add # ignore/add/remove/force + +# Add or remove space between 'decltype' and '('. +sp_decltype_paren = ignore # ignore/add/remove/force + +# (Pawn) Add or remove space after the tag keyword. +sp_after_tag = ignore # ignore/add/remove/force + +# Add or remove space inside enum '{' and '}'. +sp_inside_braces_enum = ignore # ignore/add/remove/force + +# Add or remove space inside struct/union '{' and '}'. +sp_inside_braces_struct = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}' +sp_inside_braces_oc_dict = ignore # ignore/add/remove/force + +# Add or remove space after open brace in an unnamed temporary +# direct-list-initialization. +sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force + +# Add or remove space before close brace in an unnamed temporary +# direct-list-initialization. +sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force + +# Add or remove space inside an unnamed temporary direct-list-initialization. +sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space inside '{' and '}'. +sp_inside_braces = ignore # ignore/add/remove/force + +# Add or remove space inside '{}'. +sp_inside_braces_empty = ignore # ignore/add/remove/force + +# Add or remove space around trailing return operator '->'. +#sp_trailing_return = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove space between return type and function name. A minimum of 1 +# is forced except for pointer return types. +sp_type_func = ignore # ignore/add/remove/force + +# Add or remove space between type and open brace of an unnamed temporary +# direct-list-initialization. +sp_type_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function declaration. +sp_func_proto_paren = remove # ignore/add/remove/force + +# Add or remove space between function name and '()' on function declaration +# without parameters. +sp_func_proto_paren_empty = remove # ignore/add/remove/force + +# Add or remove space between function name and '(' with a typedef specifier. +#sp_func_type_paren = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove space between alias name and '(' of a non-pointer function type typedef. +sp_func_def_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function definition +# without parameters. +sp_func_def_paren_empty = remove # ignore/add/remove/force + +# Add or remove space inside empty function '()'. +# Overrides sp_after_angle unless use_sp_after_angle_always is set to true. +sp_inside_fparens = ignore # ignore/add/remove/force + +# Add or remove space inside function '(' and ')'. +sp_inside_fparen = ignore # ignore/add/remove/force + +# Add or remove space inside the first parentheses in a function type, as in +# 'void (*x)(...)'. +sp_inside_tparen = ignore # ignore/add/remove/force + +# Add or remove space between the ')' and '(' in a function type, as in +# 'void (*x)(...)'. +sp_after_tparen_close = ignore # ignore/add/remove/force + +# Add or remove space between ']' and '(' when part of a function call. +sp_square_fparen = add # ignore/add/remove/force + +# Add or remove space between ')' and '{' of function. +sp_fparen_brace = add # ignore/add/remove/force + +# Add or remove space between ')' and '{' of s function call in object +# initialization. +# +# Overrides sp_fparen_brace. +sp_fparen_brace_initializer = ignore # ignore/add/remove/force + +# (Java) Add or remove space between ')' and '{{' of double brace initializer. +sp_fparen_dbrace = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function calls. +sp_func_call_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function calls without +# parameters. If set to ignore (the default), sp_func_call_paren is used. +sp_func_call_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between the user function name and '(' on function +# calls. You need to set a keyword to be a user function in the config file, +# like: +# set func_call_user tr _ i18n +sp_func_call_user_paren = ignore # ignore/add/remove/force + +# Add or remove space inside user function '(' and ')'. +sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force + +# Add or remove space between nested parentheses with user functions, +# i.e. '((' vs. '( ('. +sp_func_call_user_paren_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor/destructor and the open +# parenthesis. +sp_func_class_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor without parameters or destructor +# and '()'. +sp_func_class_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between 'return' and '('. +sp_return_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'return' and '{'. +sp_return_brace = ignore # ignore/add/remove/force + +# Add or remove space between '__attribute__' and '('. +sp_attribute_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. +sp_defined_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and '(' in 'throw (something)'. +sp_throw_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and anything other than '(' as in +# '@throw [...];'. +sp_after_throw = ignore # ignore/add/remove/force + +# Add or remove space between 'catch' and '(' in 'catch (something) { }'. +# If set to ignore, sp_before_sparen is used. +sp_catch_paren = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@catch' and '(' +# in '@catch (something) { }'. If set to ignore, sp_catch_paren is used. +sp_oc_catch_paren = ignore # ignore/add/remove/force + +# (OC) Add or remove space before Objective-C protocol list +# as in '@protocol Protocol' or '@interface MyClass : NSObject'. +#sp_before_oc_proto_list = ignore # ignore/add/remove/force ### not 0.69 + +# (OC) Add or remove space between class name and '(' +# in '@interface className(categoryName):BaseClass' +sp_oc_classname_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'version' and '(' +# in 'version (something) { }'. If set to ignore, sp_before_sparen is used. +sp_version_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'scope' and '(' +# in 'scope (something) { }'. If set to ignore, sp_before_sparen is used. +sp_scope_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'super' and '(' in 'super (something)'. +# +# Default: remove +sp_super_paren = remove # ignore/add/remove/force + +# Add or remove space between 'this' and '(' in 'this (something)'. +# +# Default: remove +sp_this_paren = remove # ignore/add/remove/force + +# Add or remove space between a macro name and its definition. +sp_macro = ignore # ignore/add/remove/force + +# Add or remove space between a macro function ')' and its definition. +sp_macro_func = ignore # ignore/add/remove/force + +# Add or remove space between 'else' and '{' if on the same line. +sp_else_brace = add # ignore/add/remove/force + +# Add or remove space between '}' and 'else' if on the same line. +sp_brace_else = add # ignore/add/remove/force + +# Add or remove space between '}' and the name of a typedef on the same line. +sp_brace_typedef = add # ignore/add/remove/force + +# Add or remove space before the '{' of a 'catch' statement, if the '{' and +# 'catch' are on the same line, as in 'catch (decl) {'. +sp_catch_brace = add # ignore/add/remove/force + +# (OC) Add or remove space before the '{' of a '@catch' statement, if the '{' +# and '@catch' are on the same line, as in '@catch (decl) {'. +# If set to ignore, sp_catch_brace is used. +sp_oc_catch_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'catch' if on the same line. +sp_brace_catch = add # ignore/add/remove/force + +# (OC) Add or remove space between '}' and '@catch' if on the same line. +# If set to ignore, sp_brace_catch is used. +sp_oc_brace_catch = ignore # ignore/add/remove/force + +# Add or remove space between 'finally' and '{' if on the same line. +sp_finally_brace = add # ignore/add/remove/force + +# Add or remove space between '}' and 'finally' if on the same line. +sp_brace_finally = add # ignore/add/remove/force + +# Add or remove space between 'try' and '{' if on the same line. +sp_try_brace = add # ignore/add/remove/force + +# Add or remove space between get/set and '{' if on the same line. +sp_getset_brace = add # ignore/add/remove/force + +# Add or remove space between a variable and '{' for C++ uniform +# initialization. +#sp_word_brace_init_lst = add # ignore/add/remove/force ### not 0.69 + +# Add or remove space between a variable and '{' for a namespace. +# +# Default: add +sp_word_brace_ns = add # ignore/add/remove/force + +# Add or remove space before the '::' operator. +sp_before_dc = ignore # ignore/add/remove/force + +# Add or remove space after the '::' operator. +sp_after_dc = ignore # ignore/add/remove/force + +# (D) Add or remove around the D named array initializer ':' operator. +sp_d_array_colon = ignore # ignore/add/remove/force + +# Add or remove space after the '!' (not) unary operator. +# +# Default: remove +sp_not = remove # ignore/add/remove/force + +# Add or remove space after the '~' (invert) unary operator. +# +# Default: remove +sp_inv = remove # ignore/add/remove/force + +# Add or remove space after the '&' (address-of) unary operator. This does not +# affect the spacing after a '&' that is part of a type. +# +# Default: remove +sp_addr = remove # ignore/add/remove/force + +# Add or remove space around the '.' or '->' operators. +# +# Default: remove +sp_member = remove # ignore/add/remove/force + +# Add or remove space after the '*' (dereference) unary operator. This does +# not affect the spacing after a '*' that is part of a type. +# +# Default: remove +sp_deref = remove # ignore/add/remove/force + +# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. +# +# Default: remove +sp_sign = remove # ignore/add/remove/force + +# Add or remove space between '++' and '--' the word to which it is being +# applied, as in '(--x)' or 'y++;'. +# +# Default: remove +sp_incdec = remove # ignore/add/remove/force + +# Add or remove space before a backslash-newline at the end of a line. +# +# Default: add +sp_before_nl_cont = add # ignore/add/remove/force + +# (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;' +# or '+(int) bar;'. +sp_after_oc_scope = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in message specs, +# i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'. +sp_after_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in message specs, +# i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'. +sp_before_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_after_oc_dict_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_before_oc_dict_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue: 1];'. +sp_after_send_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue :1];'. +sp_before_send_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the (type) in message specs, +# i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'. +sp_after_oc_type = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the first (type) in message specs, +# i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'. +sp_after_oc_return_type = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@selector' and '(', +# i.e. '@selector(msgName)' vs. '@selector (msgName)'. +# Also applies to '@protocol()' constructs. +sp_after_oc_at_sel = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@selector(x)' and the following word, +# i.e. '@selector(foo) a:' vs. '@selector(foo)a:'. +sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside '@selector' parentheses, +# i.e. '@selector(foo)' vs. '@selector( foo )'. +# Also applies to '@protocol()' constructs. +sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force + +# (OC) Add or remove space before a block pointer caret, +# i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'. +sp_before_oc_block_caret = ignore # ignore/add/remove/force + +# (OC) Add or remove space after a block pointer caret, +# i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'. +sp_after_oc_block_caret = ignore # ignore/add/remove/force + +# (OC) Add or remove space between the receiver and selector in a message, +# as in '[receiver selector ...]'. +sp_after_oc_msg_receiver = ignore # ignore/add/remove/force + +# (OC) Add or remove space after '@property'. +sp_after_oc_property = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@synchronized' and the open parenthesis, +# i.e. '@synchronized(foo)' vs. '@synchronized (foo)'. +sp_after_oc_synchronized = ignore # ignore/add/remove/force + +# Add or remove space around the ':' in 'b ? t : f'. +sp_cond_colon = add # ignore/add/remove/force + +# Add or remove space before the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_before = ignore # ignore/add/remove/force + +# Add or remove space after the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_after = ignore # ignore/add/remove/force + +# Add or remove space around the '?' in 'b ? t : f'. +sp_cond_question = add # ignore/add/remove/force + +# Add or remove space before the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_before = ignore # ignore/add/remove/force + +# Add or remove space after the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_after = ignore # ignore/add/remove/force + +# In the abbreviated ternary form '(a ?: b)', add or remove space between '?' +# and ':'. +# +# Overrides all other sp_cond_* options. +sp_cond_ternary_short = ignore # ignore/add/remove/force + +# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make +# sense here. +sp_case_label = ignore # ignore/add/remove/force + +# (D) Add or remove space around the D '..' operator. +sp_range = ignore # ignore/add/remove/force + +# Add or remove space after ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_after_for_colon = ignore # ignore/add/remove/force + +# Add or remove space before ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_before_for_colon = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'extern' and '(' as in 'extern (C)'. +sp_extern_paren = ignore # ignore/add/remove/force + +# Add or remove space after the opening of a C++ comment, +# i.e. '// A' vs. '//A'. +sp_cmt_cpp_start = add # ignore/add/remove/force + +# If true, space is added with sp_cmt_cpp_start will be added after doxygen +# sequences like '///', '///<', '//!' and '//!<'. +sp_cmt_cpp_doxygen = false # true/false + +# If true, space is added with sp_cmt_cpp_start will be added after Qt +# translator or meta-data comments like '//:', '//=', and '//~'. +sp_cmt_cpp_qttr = false # true/false + +# Add or remove space between #else or #endif and a trailing comment. +sp_endif_cmt = add # ignore/add/remove/force + +# Add or remove space after 'new', 'delete' and 'delete[]'. +sp_after_new = ignore # ignore/add/remove/force + +# Add or remove space between 'new' and '(' in 'new()'. +sp_between_new_paren = ignore # ignore/add/remove/force + +# Add or remove space between ')' and type in 'new(foo) BAR'. +sp_after_newop_paren = ignore # ignore/add/remove/force + +# Add or remove space inside parenthesis of the new operator +# as in 'new(foo) BAR'. +sp_inside_newop_paren = ignore # ignore/add/remove/force + +# Add or remove space after the open parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_open = ignore # ignore/add/remove/force + +# Add or remove space before the close parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_close = ignore # ignore/add/remove/force + +# Add or remove space before a trailing or embedded comment. +sp_before_tr_emb_cmt = ignore # ignore/add/remove/force + +# Number of spaces before a trailing or embedded comment. +sp_num_before_tr_emb_cmt = 0 # unsigned number + +# (Java) Add or remove space between an annotation and the open parenthesis. +sp_annotation_paren = ignore # ignore/add/remove/force + +# If true, vbrace tokens are dropped to the previous token and skipped. +sp_skip_vbrace_tokens = false # true/false + +# Add or remove space after 'noexcept'. +sp_after_noexcept = ignore # ignore/add/remove/force + +# Add or remove space after '_'. +sp_vala_after_translation = ignore # ignore/add/remove/force + +# If true, a is inserted after #define. +force_tab_after_define = false # true/false + +# +# Indenting options +# + +# The number of columns to indent per level. Usually 2, 3, 4, or 8. +# +# Default: 8 +indent_columns = 4 # unsigned number + +# The continuation indent. If non-zero, this overrides the indent of '(', '[' +# and '=' continuation indents. Negative values are OK; negative value is +# absolute and not increased for each '(' or '[' level. +# +# For FreeBSD, this is set to 4. +indent_continue = 0 # number + +# The continuation indent, only for class header line(s). If non-zero, this +# overrides the indent of 'class' continuation indents. +indent_continue_class_head = 0 # unsigned number + +# Whether to indent empty lines (i.e. lines which contain only spaces before +# the newline character). +indent_single_newlines = false # true/false + +# The continuation indent for func_*_param if they are true. If non-zero, this +# overrides the indent. +indent_param = 0 # unsigned number + +# How to use tabs when indenting code. +# +# 0: Spaces only +# 1: Indent with tabs to brace level, align with spaces (default) +# 2: Indent and align with tabs, using spaces when not on a tabstop +# +# Default: 1 +indent_with_tabs = 0 # unsigned number + +# Whether to indent comments that are not at a brace level with tabs on a +# tabstop. Requires indent_with_tabs=2. If false, will use spaces. +indent_cmt_with_tabs = false # true/false + +# Whether to indent strings broken by '\' so that they line up. +indent_align_string = false # true/false + +# The number of spaces to indent multi-line XML strings. +# Requires indent_align_string=true. +indent_xml_string = 0 # unsigned number + +# Spaces to indent '{' from level. +indent_brace = 0 # unsigned number + +# Whether braces are indented to the body level. +indent_braces = false # true/false + +# Whether to disable indenting function braces if indent_braces=true. +indent_braces_no_func = false # true/false + +# Whether to disable indenting class braces if indent_braces=true. +indent_braces_no_class = false # true/false + +# Whether to disable indenting struct braces if indent_braces=true. +indent_braces_no_struct = false # true/false + +# Whether to indent based on the size of the brace parent, +# i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. +indent_brace_parent = false # true/false + +# Whether to indent based on the open parenthesis instead of the open brace +# in '({\n'. +indent_paren_open_brace = false # true/false + +# (C#) Whether to indent the brace of a C# delegate by another level. +indent_cs_delegate_brace = false # true/false + +# (C#) Whether to indent a C# delegate (to handle delegates with no brace) by +# another level. +indent_cs_delegate_body = false # true/false + +# Whether to indent the body of a 'namespace'. +indent_namespace = false # true/false + +# Whether to indent only the first namespace, and not any nested namespaces. +# Requires indent_namespace=true. +indent_namespace_single_indent = false # true/false + +# The number of spaces to indent a namespace block. +# If set to zero, use the value indent_columns +indent_namespace_level = 0 # unsigned number + +# If the body of the namespace is longer than this number, it won't be +# indented. Requires indent_namespace=true. 0 means no limit. +indent_namespace_limit = 0 # unsigned number + +# Whether the 'extern "C"' body is indented. +indent_extern = false # true/false + +# Whether the 'class' body is indented. +indent_class = false # true/false + +# Whether to indent the stuff after a leading base class colon. +indent_class_colon = false # true/false + +# Whether to indent based on a class colon instead of the stuff after the +# colon. Requires indent_class_colon=true. +indent_class_on_colon = false # true/false + +# Whether to indent the stuff after a leading class initializer colon. +indent_constr_colon = false # true/false + +# Virtual indent from the ':' for member initializers. +# +# Default: 2 +indent_ctor_init_leading = 2 # unsigned number + +# Additional indent for constructor initializer list. +# Negative values decrease indent down to the first column. +indent_ctor_init = 0 # number + +# Whether to indent 'if' following 'else' as a new block under the 'else'. +# If false, 'else\nif' is treated as 'else if' for indenting purposes. +indent_else_if = false # true/false + +# Amount to indent variable declarations after a open brace. +# +# <0: Relative +# >=0: Absolute +indent_var_def_blk = 0 # number + +# Whether to indent continued variable declarations instead of aligning. +indent_var_def_cont = false # true/false + +# Whether to indent continued shift expressions ('<<' and '>>') instead of +# aligning. Set align_left_shift=false when enabling this. +indent_shift = false # true/false + +# Whether to force indentation of function definitions to start in column 1. +indent_func_def_force_col1 = false # true/false + +# Whether to indent continued function call parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_call_param = false # true/false + +# Whether to indent continued function definition parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_def_param = false # true/false + +# for function definitions, only if indent_func_def_param is false +# Allows to align params when appropriate and indent them when not +# behave as if it was true if paren position is more than this value +# if paren position is more than the option value +#indent_func_def_param_paren_pos_threshold = 0 # unsigned number ### not 0.69 + +# Whether to indent continued function call prototype one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_proto_param = false # true/false + +# Whether to indent continued function call declaration one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_class_param = false # true/false + +# Whether to indent continued class variable constructors one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_ctor_var_param = false # true/false + +# Whether to indent continued template parameter list one indent level, +# rather than aligning parameters under the open parenthesis. +indent_template_param = false # true/false + +# Double the indent for indent_func_xxx_param options. +# Use both values of the options indent_columns and indent_param. +indent_func_param_double = false # true/false + +# Indentation column for standalone 'const' qualifier on a function +# prototype. +indent_func_const = 0 # unsigned number + +# Indentation column for standalone 'throw' qualifier on a function +# prototype. +indent_func_throw = 0 # unsigned number + +# How to indent within a macro followed by a brace on the same line +# This allows reducing the indent in macros that have (for example) +# `do { ... } while (0)` blocks bracketing them. +# +# true: add an indent for the brace on the same line as the macro +# false: do not add an indent for the brace on the same line as the macro +# +# Default: true +#indent_macro_brace = true # true/false ### not 0.69 + +# The number of spaces to indent a continued '->' or '.'. +# Usually set to 0, 1, or indent_columns. +indent_member = 0 # unsigned number + +# Whether lines broken at '.' or '->' should be indented by a single indent. +# The indent_member option will not be effective if this is set to true. +indent_member_single = false # true/false + +# Spaces to indent single line ('//') comments on lines before code. +indent_sing_line_comments = 0 # unsigned number + +# When opening a paren for a control statement (if, for, while, etc), increase +# the indent level by this value. Negative values decrease the indent level. +#indent_sparen_extra = 0 # number ### not 0.69 + +# Whether to indent trailing single line ('//') comments relative to the code +# instead of trying to keep the same absolute column. +indent_relative_single_line_comments = false # true/false + +# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. +indent_switch_case = 0 # unsigned number + +# indent 'break' with 'case' from 'switch'. +#indent_switch_break_with_case = false # true/false ### not 0.69 + +# Whether to indent preprocessor statements inside of switch statements. +# +# Default: true +indent_switch_pp = true # true/false + +# Spaces to shift the 'case' line, without affecting any other lines. +# Usually 0. +indent_case_shift = 0 # unsigned number + +# Spaces to indent '{' from 'case'. By default, the brace will appear under +# the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK. +indent_case_brace = 0 # number + +# Whether to indent comments found in first column. +indent_col1_comment = false # true/false + +# Whether to indent multi string literal in first column. +indent_col1_multi_string_literal = false # true/false + +# How to indent goto labels. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_label = 1 # number + +# How to indent access specifiers that are followed by a +# colon. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_access_spec = 1 # number + +# Whether to indent the code after an access specifier by one level. +# If true, this option forces 'indent_access_spec=0'. +indent_access_spec_body = false # true/false + +# If an open parenthesis is followed by a newline, whether to indent the next +# line so that it lines up after the open parenthesis (not recommended). +indent_paren_nl = false # true/false + +# How to indent a close parenthesis after a newline. +# +# 0: Indent to body level (default) +# 1: Align under the open parenthesis +# 2: Indent to the brace level +indent_paren_close = 0 # unsigned number + +# Whether to indent the open parenthesis of a function definition, +# if the parenthesis is on its own line. +indent_paren_after_func_def = false # true/false + +# Whether to indent the open parenthesis of a function declaration, +# if the parenthesis is on its own line. +indent_paren_after_func_decl = false # true/false + +# Whether to indent the open parenthesis of a function call, +# if the parenthesis is on its own line. +indent_paren_after_func_call = false # true/false + +# Whether to indent a comma when inside a parenthesis. +# If true, aligns under the open parenthesis. +indent_comma_paren = false # true/false + +# Whether to indent a Boolean operator when inside a parenthesis. +# If true, aligns under the open parenthesis. +indent_bool_paren = false # true/false + +# Whether to indent a semicolon when inside a for parenthesis. +# If true, aligns under the open for parenthesis. +indent_semicolon_for_paren = false # true/false + +# Whether to align the first expression to following ones +# if indent_bool_paren=true. +indent_first_bool_expr = false # true/false + +# Whether to align the first expression to following ones +# if indent_semicolon_for_paren=true. +indent_first_for_expr = false # true/false + +# If an open square is followed by a newline, whether to indent the next line +# so that it lines up after the open square (not recommended). +indent_square_nl = false # true/false + +# (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies. +indent_preserve_sql = false # true/false + +# Whether to align continued statements at the '='. If false or if the '=' is +# followed by a newline, the next line is indent one tab. +# +# Default: true +indent_align_assign = true # true/false + +# If true, the indentation of the chunks after a '=' sequence will be set at +# LHS token indentation column before '='. +#indent_off_after_assign = false # true/false ### not 0.69 + +# Whether to align continued statements at the '('. If false or the '(' is +# followed by a newline, the next line indent is one tab. +# +# Default: true +indent_align_paren = true # true/false + +# (OC) Whether to indent Objective-C code inside message selectors. +#indent_oc_inside_msg_sel = false # true/false ### not 0.69 + +# (OC) Whether to indent Objective-C blocks at brace level instead of usual +# rules. +indent_oc_block = false # true/false + +# (OC) Indent for Objective-C blocks in a message relative to the parameter +# name. +# +# =0: Use indent_oc_block rules +# >0: Use specified number of spaces to indent +indent_oc_block_msg = 0 # unsigned number + +# (OC) Minimum indent for subsequent parameters +indent_oc_msg_colon = 0 # unsigned number + +# (OC) Whether to prioritize aligning with initial colon (and stripping spaces +# from lines, if necessary). +# +# Default: true +indent_oc_msg_prioritize_first_colon = true # true/false + +# (OC) Whether to indent blocks the way that Xcode does by default +# (from the keyword if the parameter is on its own line; otherwise, from the +# previous indentation level). Requires indent_oc_block_msg=true. +indent_oc_block_msg_xcode_style = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a +# message keyword. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_keyword = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a message +# colon. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_colon = false # true/false + +# (OC) Whether to indent blocks from where the block caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_caret = false # true/false + +# (OC) Whether to indent blocks from where the brace caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_brace = false # true/false + +# When indenting after virtual brace open and newline add further spaces to +# reach this minimum indent. +indent_min_vbrace_open = 0 # unsigned number + +# Whether to add further spaces after regular indent to reach next tabstop +# when identing after virtual brace open and newline. +indent_vbrace_open_on_tabstop = false # true/false + +# How to indent after a brace followed by another token (not a newline). +# true: indent all contained lines to match the token +# false: indent all contained lines to match the brace +# +# Default: true +indent_token_after_brace = true # true/false + +# Whether to indent the body of a C++11 lambda. +indent_cpp_lambda_body = false # true/false + +# How to indent compound literals that are being returned. +# true: add both the indent from return & the compound literal open brace (ie: +# 2 indent levels) +# false: only indent 1 level, don't add the indent for the open brace, only add +# the indent for the return. +# +# Default: true +#indent_compound_literal_return = true # true/false ### not 0.69 + +# (C#) Whether to indent a 'using' block if no braces are used. +# +# Default: true +indent_using_block = true # true/false + +# How to indent the continuation of ternary operator. +# +# 0: Off (default) +# 1: When the `if_false` is a continuation, indent it under `if_false` +# 2: When the `:` is a continuation, indent it under `?` +indent_ternary_operator = 0 # unsigned number + +# Whether to indent the statments inside ternary operator. +#indent_inside_ternary_operator = false # true/false ### not 0.69 + +# If true, the indentation of the chunks after a `return` sequence will be set at return indentation column. +#indent_off_after_return = false # true/false ### not 0.69 + +# If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column. +indent_off_after_return_new = false # true/false + +# If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token. +indent_single_after_return = false # true/false + +# Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they +# have their own indentation). +indent_ignore_asm_block = false # true/false + +# +# Newline adding and removing options +# + +# Whether to collapse empty blocks between '{' and '}'. +nl_collapse_empty_body = false # true/false + +# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. +nl_assign_leave_one_liners = false # true/false + +# Don't split one-line braced statements inside a 'class xx { }' body. +nl_class_leave_one_liners = false # true/false + +# Don't split one-line enums, as in 'enum foo { BAR = 15 };' +nl_enum_leave_one_liners = false # true/false + +# Don't split one-line get or set functions. +nl_getset_leave_one_liners = false # true/false + +# (C#) Don't split one-line property get or set functions. +nl_cs_property_leave_one_liners = false # true/false + +# Don't split one-line function definitions, as in 'int foo() { return 0; }'. +# might modify nl_func_type_name +nl_func_leave_one_liners = false # true/false + +# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. +nl_cpp_lambda_leave_one_liners = false # true/false + +# Don't split one-line if/else statements, as in 'if(...) b++;'. +nl_if_leave_one_liners = false # true/false + +# Don't split one-line while statements, as in 'while(...) b++;'. +nl_while_leave_one_liners = false # true/false + +# Don't split one-line for statements, as in 'for(...) b++;'. +nl_for_leave_one_liners = false # true/false + +# (OC) Don't split one-line Objective-C messages. +nl_oc_msg_leave_one_liner = false # true/false + +# (OC) Add or remove newline between method declaration and '{'. +nl_oc_mdef_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between Objective-C block signature and '{'. +nl_oc_block_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove blank line before '@interface' statement. +#nl_oc_before_interface = ignore # ignore/add/remove/force ### not 0.69 + +# (OC) Add or remove blank line before '@implementation' statement. +#nl_oc_before_implementation = ignore # ignore/add/remove/force ### not 0.69 + +# (OC) Add or remove blank line before '@end' statement. +#nl_oc_before_end = ignore # ignore/add/remove/force ### not 0.69 + +# (OC) Add or remove newline between '@interface' and '{'. +nl_oc_interface_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between '@implementation' and '{'. +nl_oc_implementation_brace = ignore # ignore/add/remove/force + +# Add or remove newlines at the start of the file. +nl_start_of_file = remove # ignore/add/remove/force + +# The minimum number of newlines at the start of the file (only used if +# nl_start_of_file is 'add' or 'force'). +nl_start_of_file_min = 0 # unsigned number + +# Add or remove newline at the end of the file. +nl_end_of_file = ignore # ignore/add/remove/force + +# The minimum number of newlines at the end of the file (only used if +# nl_end_of_file is 'add' or 'force'). +nl_end_of_file_min = 0 # unsigned number + +# Add or remove newline between '=' and '{'. +nl_assign_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between '=' and '['. +nl_assign_square = ignore # ignore/add/remove/force + +# Add or remove newline between '[]' and '{'. +nl_tsquare_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline after '= ['. Will also affect the newline before +# the ']'. +nl_after_square_assign = ignore # ignore/add/remove/force + +# Add or remove newline between a function call's ')' and '{', as in +# 'list_for_each(item, &list) { }'. +nl_fcall_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum' and '{'. +nl_enum_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'enum' and 'class'. +nl_enum_class = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class' and the identifier. +nl_enum_class_identifier = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class' type and ':'. +nl_enum_identifier_colon = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class identifier :' and type. +nl_enum_colon_type = ignore # ignore/add/remove/force + +# Add or remove newline between 'struct and '{'. +nl_struct_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'union' and '{'. +nl_union_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'if' and '{'. +nl_if_brace = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'else'. +nl_brace_else = remove # ignore/add/remove/force + +# Add or remove newline between 'else if' and '{'. If set to ignore, +# nl_if_brace is used instead. +nl_elseif_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'else' and '{'. +nl_else_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'else' and 'if'. +nl_else_if = remove # ignore/add/remove/force + +# Add or remove newline before '{' opening brace +#nl_before_opening_brace_func_class_def = remove # ignore/add/remove/force ### not 0.69 + +# Add or remove newline before 'if'/'else if' closing parenthesis. +nl_before_if_closing_paren = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'finally'. +nl_brace_finally = remove # ignore/add/remove/force + +# Add or remove newline between 'finally' and '{'. +nl_finally_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'try' and '{'. +nl_try_brace = remove # ignore/add/remove/force + +# Add or remove newline between get/set and '{'. +nl_getset_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'for' and '{'. +nl_for_brace = remove # ignore/add/remove/force + +# Add or remove newline before the '{' of a 'catch' statement, as in +# 'catch (decl) {'. +nl_catch_brace = remove # ignore/add/remove/force + +# (OC) Add or remove newline before the '{' of a '@catch' statement, as in +# '@catch (decl) {'. If set to ignore, nl_catch_brace is used. +nl_oc_catch_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'catch'. +nl_brace_catch = remove # ignore/add/remove/force + +# (OC) Add or remove newline between '}' and '@catch'. If set to ignore, +# nl_brace_catch is used. +nl_oc_brace_catch = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and ']'. +nl_brace_square = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and ')' in a function invocation. +nl_brace_fparen = ignore # ignore/add/remove/force + +# Add or remove newline between 'while' and '{'. +nl_while_brace = remove # ignore/add/remove/force + +# (D) Add or remove newline between 'scope (x)' and '{'. +nl_scope_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'unittest' and '{'. +nl_unittest_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'version (x)' and '{'. +nl_version_brace = ignore # ignore/add/remove/force + +# (C#) Add or remove newline between 'using' and '{'. +nl_using_brace = ignore # ignore/add/remove/force + +# Add or remove newline between two open or close braces. Due to general +# newline/brace handling, REMOVE may not work. +nl_brace_brace = add # ignore/add/remove/force + +# Add or remove newline between 'do' and '{'. +nl_do_brace = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'while' of 'do' statement. +nl_brace_while = remove # ignore/add/remove/force + +# Add or remove newline between 'switch' and '{'. +nl_switch_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'synchronized' and '{'. +nl_synchronized_brace = remove # ignore/add/remove/force + +# Add a newline between ')' and '{' if the ')' is on a different line than the +# if/for/etc. +# +# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and +# nl_catch_brace. +nl_multi_line_cond = false # true/false + +# Add a newline after '(' if an if/for/while/switch condition spans multiple +# lines +#nl_multi_line_sparen_open = ignore # ignore/add/remove/force ### not 0.69 + +# Add a newline before ')' if an if/for/while/switch condition spans multiple +# lines. Overrides nl_before_if_closing_paren if both are specified. +#nl_multi_line_sparen_close = ignore # ignore/add/remove/force ### not 0.69 + +# Force a newline in a define after the macro name for multi-line defines. +nl_multi_line_define = false # true/false + +# Whether to add a newline before 'case', and a blank line before a 'case' +# statement that follows a ';' or '}'. +nl_before_case = false # true/false + +# Whether to add a newline after a 'case' statement. +nl_after_case = false # true/false + +# Add or remove newline between a case ':' and '{'. +# +# Overrides nl_after_case. +nl_case_colon_brace = ignore # ignore/add/remove/force + +# Add or remove newline between ')' and 'throw'. +nl_before_throw = ignore # ignore/add/remove/force + +# Add or remove newline between 'namespace' and '{'. +nl_namespace_brace = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class. +nl_template_class = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class declaration. +# +# Overrides nl_template_class. +#nl_template_class_decl = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<>' of a specialized class declaration. +# +# Overrides nl_template_class_decl. +#nl_template_class_decl_special = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<...>' of a template class definition. +# +# Overrides nl_template_class. +#nl_template_class_def = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<>' of a specialized class definition. +# +# Overrides nl_template_class_def. +#nl_template_class_def_special = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<...>' of a template function. +#nl_template_func = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<...>' of a template function +# declaration. +# +# Overrides nl_template_func. +#nl_template_func_decl = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<>' of a specialized function +# declaration. +# +# Overrides nl_template_func_decl. +#nl_template_func_decl_special = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<...>' of a template function +# definition. +# +# Overrides nl_template_func. +#nl_template_func_def = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<>' of a specialized function +# definition. +# +# Overrides nl_template_func_def. +#nl_template_func_def_special = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline after 'template<...>' of a template variable. +#nl_template_var = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline between 'template<...>' and 'using' of a templated +# type alias. +#nl_template_using = ignore # ignore/add/remove/force ### not 0.69 + +# Add or remove newline between 'class' and '{'. +nl_class_brace = ignore # ignore/add/remove/force + +# Add or remove newline before or after (depending on pos_class_comma, +# may not be IGNORE) each',' in the base class list. +nl_class_init_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in the constructor member +# initialization. Related to nl_constr_colon, pos_constr_colon and +# pos_constr_comma. +nl_constr_init_args = ignore # ignore/add/remove/force + +# Add or remove newline before first element, after comma, and after last +# element, in 'enum'. +nl_enum_own_lines = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a function +# definition. +# might be modified by nl_func_leave_one_liners +nl_func_type_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name inside a class +# definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name +# is used instead. +nl_func_type_name_class = ignore # ignore/add/remove/force + +# Add or remove newline between class specification and '::' +# in 'void A::f() { }'. Only appears in separate member implementation (does +# not appear with in-line implementation). +nl_func_class_scope = ignore # ignore/add/remove/force + +# Add or remove newline between function scope and name, as in +# 'void A :: f() { }'. +nl_func_scope_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a prototype. +nl_func_proto_type_name = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# declaration. +nl_func_paren = remove # ignore/add/remove/force + +# Overrides nl_func_paren for functions with no parameters. +nl_func_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# definition. +nl_func_def_paren = remove # ignore/add/remove/force + +# Overrides nl_func_def_paren for functions with no parameters. +nl_func_def_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# call. +nl_func_call_paren = ignore # ignore/add/remove/force + +# Overrides nl_func_call_paren for functions with no parameters. +nl_func_call_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline after '(' in a function declaration. +nl_func_decl_start = remove # ignore/add/remove/force + +# Add or remove newline after '(' in a function definition. +nl_func_def_start = remove # ignore/add/remove/force + +# Overrides nl_func_decl_start when there is only one parameter. +nl_func_decl_start_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_start when there is only one parameter. +nl_func_def_start_single = ignore # ignore/add/remove/force + +# Whether to add a newline after '(' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_start is used instead. +nl_func_decl_start_multi_line = false # true/false + +# Whether to add a newline after '(' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_start is used instead. +nl_func_def_start_multi_line = false # true/false + +# Add or remove newline after each ',' in a function declaration. +nl_func_decl_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function definition. +nl_func_def_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function call. +#nl_func_call_args = ignore # ignore/add/remove/force ### not 0.69 + +# Whether to add a newline after each ',' in a function declaration if '(' +# and ')' are in different lines. If false, nl_func_decl_args is used instead. +nl_func_decl_args_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function definition if '(' +# and ')' are in different lines. If false, nl_func_def_args is used instead. +nl_func_def_args_multi_line = false # true/false + +# Add or remove newline before the ')' in a function declaration. +nl_func_decl_end = remove # ignore/add/remove/force + +# Add or remove newline before the ')' in a function definition. +nl_func_def_end = remove # ignore/add/remove/force + +# Overrides nl_func_decl_end when there is only one parameter. +nl_func_decl_end_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_end when there is only one parameter. +nl_func_def_end_single = ignore # ignore/add/remove/force + +# Whether to add a newline before ')' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_end is used instead. +nl_func_decl_end_multi_line = false # true/false + +# Whether to add a newline before ')' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_end is used instead. +nl_func_def_end_multi_line = false # true/false + +# Add or remove newline between '()' in a function declaration. +nl_func_decl_empty = remove # ignore/add/remove/force + +# Add or remove newline between '()' in a function definition. +nl_func_def_empty = remove # ignore/add/remove/force + +# Add or remove newline between '()' in a function call. +nl_func_call_empty = remove # ignore/add/remove/force + +# Whether to add a newline after '(' in a function call, +# has preference over nl_func_call_start_multi_line. +nl_func_call_start = ignore # ignore/add/remove/force + +# Whether to add a newline before ')' in a function call. +#nl_func_call_end = ignore # ignore/add/remove/force ### not 0.69 + +# Whether to add a newline after '(' in a function call if '(' and ')' are in +# different lines. +nl_func_call_start_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function call if '(' and ')' +# are in different lines. +nl_func_call_args_multi_line = false # true/false + +# Whether to add a newline before ')' in a function call if '(' and ')' are in +# different lines. +nl_func_call_end_multi_line = false # true/false + +# Whether to respect nl_func_call_XXX option incase of closure args. +#nl_func_call_args_multi_line_ignore_closures = false # true/false ### not 0.69 + +# Whether to add a newline after '<' of a template parameter list. +#nl_template_start = false # true/false ### not 0.69 + +# Whether to add a newline after each ',' in a template parameter list. +#nl_template_args = false # true/false ### not 0.69 + +# Whether to add a newline before '>' of a template parameter list. +#nl_template_end = false # true/false ### not 0.69 + +# (OC) Whether to put each Objective-C message parameter on a separate line. +# See nl_oc_msg_leave_one_liner. +nl_oc_msg_args = false # true/false + +# Add or remove newline between function signature and '{'. +nl_fdef_brace = ignore # ignore/add/remove/force + +# Add or remove newline between function signature and '{', +# if signature ends with ')'. Overrides nl_fdef_brace. +nl_fdef_brace_cond = ignore # ignore/add/remove/force + +# Add or remove newline between C++11 lambda signature and '{'. +nl_cpp_ldef_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'return' and the return expression. +nl_return_expr = ignore # ignore/add/remove/force + +# Whether to add a newline after semicolons, except in 'for' statements. +nl_after_semicolon = false # true/false + +# (Java) Add or remove newline between the ')' and '{{' of the double brace +# initializer. +nl_paren_dbrace_open = ignore # ignore/add/remove/force + +# Whether to add a newline after the type in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst = ignore # ignore/add/remove/force + +# Whether to add a newline after the open brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_open = ignore # ignore/add/remove/force + +# Whether to add a newline before the close brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_close = ignore # ignore/add/remove/force + +# Whether to add a newline after '{'. This also adds a newline before the +# matching '}'. +nl_after_brace_open = false # true/false + +# Whether to add a newline between the open brace and a trailing single-line +# comment. Requires nl_after_brace_open=true. +nl_after_brace_open_cmt = false # true/false + +# Whether to add a newline after a virtual brace open with a non-empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open = false # true/false + +# Whether to add a newline after a virtual brace open with an empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open_empty = false # true/false + +# Whether to add a newline after '}'. Does not apply if followed by a +# necessary ';'. +nl_after_brace_close = false # true/false + +# Whether to add a newline after a virtual brace close, +# as in 'if (foo) a++; return;'. +nl_after_vbrace_close = false # true/false + +# Add or remove newline between the close brace and identifier, +# as in 'struct { int a; } b;'. Affects enumerations, unions and +# structures. If set to ignore, uses nl_after_brace_close. +nl_brace_struct_var = ignore # ignore/add/remove/force + +# Whether to alter newlines in '#define' macros. +nl_define_macro = false # true/false + +# Whether to alter newlines between consecutive parenthesis closes. The number +# of closing parentheses in a line will depend on respective open parenthesis +# lines. +nl_squeeze_paren_close = false # true/false + +# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and +# '#endif'. Does not affect top-level #ifdefs. +nl_squeeze_ifdef = false # true/false + +# Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. +nl_squeeze_ifdef_top_level = false # true/false + +# Add or remove blank line before 'if'. +nl_before_if = add # ignore/add/remove/force + +# Add or remove blank line after 'if' statement. Add/Force work only if the +# next token is not a closing brace. +nl_after_if = add # ignore/add/remove/force + +# Add or remove blank line before 'for'. +nl_before_for = add # ignore/add/remove/force + +# Add or remove blank line after 'for' statement. +nl_after_for = add # ignore/add/remove/force + +# Add or remove blank line before 'while'. +nl_before_while = add # ignore/add/remove/force + +# Add or remove blank line after 'while' statement. +nl_after_while = add # ignore/add/remove/force + +# Add or remove blank line before 'switch'. +nl_before_switch = add # ignore/add/remove/force + +# Add or remove blank line after 'switch' statement. +nl_after_switch = add # ignore/add/remove/force + +# Add or remove blank line before 'synchronized'. +nl_before_synchronized = add # ignore/add/remove/force + +# Add or remove blank line after 'synchronized' statement. +nl_after_synchronized = add # ignore/add/remove/force + +# Add or remove blank line before 'do'. +nl_before_do = add # ignore/add/remove/force + +# Add or remove blank line after 'do/while' statement. +nl_after_do = add # ignore/add/remove/force + +# Whether to put a blank line before 'return' statements, unless after an open +# brace. +nl_before_return = false # true/false + +# Whether to put a blank line after 'return' statements, unless followed by a +# close brace. +nl_after_return = false # true/false + +# Whether to put a blank line before a member '.' or '->' operators. +#nl_before_member = ignore # ignore/add/remove/force ### not 0.69 + +# (Java) Whether to put a blank line after a member '.' or '->' operators. +#nl_after_member = ignore # ignore/add/remove/force ### not 0.69 + +# Whether to double-space commented-entries in 'struct'/'union'/'enum'. +nl_ds_struct_enum_cmt = false # true/false + +# Whether to force a newline before '}' of a 'struct'/'union'/'enum'. +# (Lower priority than eat_blanks_before_close_brace.) +nl_ds_struct_enum_close_brace = false # true/false + +# Add or remove newline before or after (depending on pos_class_colon) a class +# colon, as in 'class Foo : public Bar'. +nl_class_colon = ignore # ignore/add/remove/force + +# Add or remove newline around a class constructor colon. The exact position +# depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma. +nl_constr_colon = ignore # ignore/add/remove/force + +# Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }' +# into a single line. If true, prevents other brace newline rules from turning +# such code into four lines. +nl_namespace_two_to_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced if statements, turning them +# into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'. +nl_create_if_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced for statements, turning them +# into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'. +nl_create_for_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced while statements, turning +# them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'. +nl_create_while_one_liner = false # true/false + +# Whether to collapse a function definition whose body (not counting braces) +# is only one line so that the entire definition (prototype, braces, body) is +# a single line. +nl_create_func_def_one_liner = false # true/false + +# Whether to collapse a function definition whose body (not counting braces) +# is only one line so that the entire definition (prototype, braces, body) is +# a single line. +#nl_create_list_one_liner = false # true/false ### not 0.69 + +# Whether to split one-line simple unbraced if statements into two lines by +# adding a newline, as in 'if(b) i++;'. +nl_split_if_one_liner = false # true/false + +# Whether to split one-line simple unbraced for statements into two lines by +# adding a newline, as in 'for (...) stmt;'. +nl_split_for_one_liner = false # true/false + +# Whether to split one-line simple unbraced while statements into two lines by +# adding a newline, as in 'while (expr) stmt;'. +nl_split_while_one_liner = false # true/false + +# +# Blank line options +# + +# The maximum number of consecutive newlines (3 = 2 blank lines). +nl_max = 0 # unsigned number + +# The maximum number of consecutive newlines in a function. +nl_max_blank_in_func = 0 # unsigned number + +# The number of newlines before a function prototype. +nl_before_func_body_proto = 0 # unsigned number + +# The number of newlines before a multi-line function definition. +nl_before_func_body_def = 0 # unsigned number + +# The number of newlines before a class constructor/destructor prototype. +nl_before_func_class_proto = 0 # unsigned number + +# The number of newlines before a class constructor/destructor definition. +nl_before_func_class_def = 0 # unsigned number + +# The number of newlines after a function prototype. +nl_after_func_proto = 0 # unsigned number + +# The number of newlines after a function prototype, if not followed by +# another function prototype. +nl_after_func_proto_group = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype. +nl_after_func_class_proto = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype, +# if not followed by another constructor/destructor prototype. +nl_after_func_class_proto_group = 0 # unsigned number + +# Whether one-line method definitions inside a class body should be treated +# as if they were prototypes for the purposes of adding newlines. +# +# Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def +# and nl_before_func_class_def for one-liners. +nl_class_leave_one_liner_groups = false # true/false + +# The number of newlines after '}' of a multi-line function body. +nl_after_func_body = 0 # unsigned number + +# The number of newlines after '}' of a multi-line function body in a class +# declaration. Also affects class constructors/destructors. +# +# Overrides nl_after_func_body. +nl_after_func_body_class = 0 # unsigned number + +# The number of newlines after '}' of a single line function body. Also +# affects class constructors/destructors. +# +# Overrides nl_after_func_body and nl_after_func_body_class. +nl_after_func_body_one_liner = 0 # unsigned number + +# The number of blank lines after a block of variable definitions at the top +# of a function body. +# +# 0: No change (default). +nl_func_var_def_blk = 0 # unsigned number + +# The number of newlines before a block of typedefs. If nl_after_access_spec +# is non-zero, that option takes precedence. +# +# 0: No change (default). +nl_typedef_blk_start = 0 # unsigned number + +# The number of newlines after a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_in = 0 # unsigned number + +# The number of newlines before a block of variable definitions not at the top +# of a function body. If nl_after_access_spec is non-zero, that option takes +# precedence. +# +# 0: No change (default). +nl_var_def_blk_start = 0 # unsigned number + +# The number of newlines after a block of variable definitions not at the top +# of a function body. +# +# 0: No change (default). +nl_var_def_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of variable +# definitions. +# +# 0: No change (default). +nl_var_def_blk_in = 0 # unsigned number + +# The minimum number of newlines before a multi-line comment. +# Doesn't apply if after a brace open or another multi-line comment. +nl_before_block_comment = 0 # unsigned number + +# The minimum number of newlines before a single-line C comment. +# Doesn't apply if after a brace open or other single-line C comments. +nl_before_c_comment = 0 # unsigned number + +# The minimum number of newlines before a CPP comment. +# Doesn't apply if after a brace open or other CPP comments. +nl_before_cpp_comment = 0 # unsigned number + +# Whether to force a newline after a multi-line comment. +nl_after_multiline_comment = false # true/false + +# Whether to force a newline after a label's colon. +nl_after_label_colon = false # true/false + +# The number of newlines after '}' or ';' of a struct/enum/union definition. +nl_after_struct = 0 # unsigned number + +# The number of newlines before a class definition. +nl_before_class = 0 # unsigned number + +# The number of newlines after '}' or ';' of a class definition. +nl_after_class = 0 # unsigned number + +# The number of newlines before a namespace. +#nl_before_namespace = 0 # unsigned number ### not 0.69 + +# The number of newlines after '{' of a namespace. This also adds newlines +# before the matching '}'. +# +# 0: Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if +# applicable, otherwise no change. +# +# Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace. +nl_inside_namespace = 0 # unsigned number + +# The number of newlines after '}' of a namespace. +#nl_after_namespace = 0 # unsigned number ### not 0.69 + +# The number of newlines before an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +nl_before_access_spec = 0 # unsigned number + +# The number of newlines after an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +# +# Overrides nl_typedef_blk_start and nl_var_def_blk_start. +nl_after_access_spec = 0 # unsigned number + +# The number of newlines between a function definition and the function +# comment, as in '// comment\n void foo() {...}'. +# +# 0: No change (default). +nl_comment_func_def = 0 # unsigned number + +# The number of newlines after a try-catch-finally block that isn't followed +# by a brace close. +# +# 0: No change (default). +nl_after_try_catch_finally = 0 # unsigned number + +# (C#) The number of newlines before and after a property, indexer or event +# declaration. +# +# 0: No change (default). +nl_around_cs_property = 0 # unsigned number + +# (C#) The number of newlines between the get/set/add/remove handlers. +# +# 0: No change (default). +nl_between_get_set = 0 # unsigned number + +# (C#) Add or remove newline between property and the '{'. +nl_property_brace = ignore # ignore/add/remove/force + +# Whether to remove blank lines after '{'. +eat_blanks_after_open_brace = false # true/false + +# Whether to remove blank lines before '}'. +eat_blanks_before_close_brace = false # true/false + +# How aggressively to remove extra newlines not in preprocessor. +# +# 0: No change (default) +# 1: Remove most newlines not handled by other config +# 2: Remove all newlines and reformat completely by config +nl_remove_extra_newlines = 0 # unsigned number + +# (Java) Add or remove newline after an annotation statement. Only affects +# annotations that are after a newline. +nl_after_annotation = ignore # ignore/add/remove/force + +# (Java) Add or remove newline between two annotations. +nl_between_annotation = ignore # ignore/add/remove/force + +# The number of newlines before a whole-file #ifdef. +# +# 0: No change (default). +#nl_before_whole_file_ifdef = 0 # unsigned number ### not 0.69 + +# The number of newlines after a whole-file #ifdef. +# +# 0: No change (default). +#nl_after_whole_file_ifdef = 0 # unsigned number ### not 0.69 + +# The number of newlines before a whole-file #endif. +# +# 0: No change (default). +#nl_before_whole_file_endif = 0 # unsigned number ### not 0.69 + +# The number of newlines after a whole-file #endif. +# +# 0: No change (default). +#nl_after_whole_file_endif = 0 # unsigned number ### not 0.69 + +# +# Positioning options +# + +# The position of arithmetic operators in wrapped expressions. +pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of assignment in wrapped expressions. Do not affect '=' +# followed by '{'. +pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of Boolean operators in wrapped expressions. +pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of comparison operators in wrapped expressions. +pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of conditional operators, as in the '?' and ':' of +# 'expr ? stmt : stmt', in wrapped expressions. +pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in wrapped expressions. +pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in enum entries. +pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the base class list if there is more than one +# line. Affects nl_class_init_args. +pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the constructor initialization list. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. +pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of trailing/leading class colon, between class and base class +# list. Affects nl_class_colon. +pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of colons between constructor and member initialization. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. +pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# +# Line splitting options +# + +# Try to limit code width to N columns. +code_width = 0 # unsigned number + +# Whether to fully split long 'for' statements at semi-colons. +ls_for_split_full = false # true/false + +# Whether to fully split long function prototypes/calls at commas. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_func_split_full = false # true/false + +# Whether to split lines as close to code_width as possible and ignore some +# groupings. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_code_width = false # true/false + +# +# Code alignment options (not left column spaces/tabs) +# + +# Whether to keep non-indenting tabs. +align_keep_tabs = false # true/false + +# Whether to use tabs for aligning. +align_with_tabs = false # true/false + +# Whether to bump out to the next tab when aligning. +align_on_tabstop = false # true/false + +# Whether to right-align numbers. +align_number_right = false # true/false + +# Whether to keep whitespace not required for alignment. +align_keep_extra_space = false # true/false + +# Whether to align variable definitions in prototypes and functions. +align_func_params = false # true/false + +# The span for aligning parameter definitions in function on parameter name. +# +# 0: Don't align (default). +align_func_params_span = 0 # unsigned number + +# The threshold for aligning function parameter definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_params_thresh = 0 # number + +# The gap for aligning function parameter definitions. +align_func_params_gap = 0 # unsigned number + +# The span for aligning constructor value. +# +# 0: Don't align (default). +align_constr_value_span = 0 # unsigned number + +# The threshold for aligning constructor value. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_constr_value_thresh = 0 # number + +# The gap for aligning constructor value. +align_constr_value_gap = 0 # unsigned number + +# Whether to align parameters in single-line functions that have the same +# name. The function names must already be aligned with each other. +align_same_func_call_params = false # true/false + +# The span for aligning function-call parameters for single line functions. +# +# 0: Don't align (default). +align_same_func_call_params_span = 0 # unsigned number + +# The threshold for aligning function-call parameters for single line +# functions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_same_func_call_params_thresh = 0 # number + +# The span for aligning variable definitions. +# +# 0: Don't align (default). +align_var_def_span = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of variable definitions. +# +# 0: Part of the type 'void * foo;' (default) +# 1: Part of the variable 'void *foo;' +# 2: Dangling 'void *foo;' +# Dangling: the '*' will not be taken into account when aligning. +align_var_def_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of variable definitions. +# +# 0: Part of the type 'long & foo;' (default) +# 1: Part of the variable 'long &foo;' +# 2: Dangling 'long &foo;' +# Dangling: the '&' will not be taken into account when aligning. +align_var_def_amp_style = 0 # unsigned number + +# The threshold for aligning variable definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_def_thresh = 0 # number + +# The gap for aligning variable definitions. +align_var_def_gap = 0 # unsigned number + +# Whether to align the colon in struct bit fields. +align_var_def_colon = false # true/false + +# The gap for aligning the colon in struct bit fields. +align_var_def_colon_gap = 0 # unsigned number + +# Whether to align any attribute after the variable name. +align_var_def_attribute = false # true/false + +# Whether to align inline struct/enum/union variable definitions. +align_var_def_inline = false # true/false + +# The span for aligning on '=' in assignments. +# +# 0: Don't align (default). +align_assign_span = 0 # unsigned number + +# The span for aligning on '=' in function prototype modifier. +# +# 0: Don't align (default). +align_assign_func_proto_span = 0 # unsigned number + +# The threshold for aligning on '=' in assignments. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_assign_thresh = 0 # number + +# How to apply align_assign_span to function declaration "assignments", i.e. +# 'virtual void foo() = 0' or '~foo() = {default|delete}'. +# +# 0: Align with other assignments (default) +# 1: Align with each other, ignoring regular assignments +# 2: Don't align +align_assign_decl_func = 0 # unsigned number + +# The span for aligning on '=' in enums. +# +# 0: Don't align (default). +align_enum_equ_span = 0 # unsigned number + +# The threshold for aligning on '=' in enums. +# Use a negative number for absolute thresholds. +# +# 0: no limit (default). +align_enum_equ_thresh = 0 # number + +# The span for aligning class member definitions. +# +# 0: Don't align (default). +align_var_class_span = 0 # unsigned number + +# The threshold for aligning class member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_class_thresh = 0 # number + +# The gap for aligning class member definitions. +align_var_class_gap = 0 # unsigned number + +# The span for aligning struct/union member definitions. +# +# 0: Don't align (default). +align_var_struct_span = 0 # unsigned number + +# The threshold for aligning struct/union member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_struct_thresh = 0 # number + +# The gap for aligning struct/union member definitions. +align_var_struct_gap = 0 # unsigned number + +# The span for aligning struct initializer values. +# +# 0: Don't align (default). +align_struct_init_span = 0 # unsigned number + +# The span for aligning single-line typedefs. +# +# 0: Don't align (default). +align_typedef_span = 0 # unsigned number + +# The minimum space between the type and the synonym of a typedef. +align_typedef_gap = 0 # unsigned number + +# How to align typedef'd functions with other typedefs. +# +# 0: Don't mix them at all (default) +# 1: Align the open parenthesis with the types +# 2: Align the function type name with the other type names +align_typedef_func = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int * pint;' (default) +# 1: Part of type name: 'typedef int *pint;' +# 2: Dangling: 'typedef int *pint;' +# Dangling: the '*' will not be taken into account when aligning. +align_typedef_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int & intref;' (default) +# 1: Part of type name: 'typedef int &intref;' +# 2: Dangling: 'typedef int &intref;' +# Dangling: the '&' will not be taken into account when aligning. +align_typedef_amp_style = 0 # unsigned number + +# The span for aligning comments that end lines. +# +# 0: Don't align (default). +align_right_cmt_span = 0 # unsigned number + +# Minimum number of columns between preceding text and a trailing comment in +# order for the comment to qualify for being aligned. Must be non-zero to have +# an effect. +align_right_cmt_gap = 0 # unsigned number + +# If aligning comments, whether to mix with comments after '}' and #endif with +# less than three spaces before the comment. +align_right_cmt_mix = false # true/false + +# Whether to only align trailing comments that are at the same brace level. +align_right_cmt_same_level = false # true/false + +# Minimum column at which to align trailing comments. Comments which are +# aligned beyond this column, but which can be aligned in a lesser column, +# may be "pulled in". +# +# 0: Ignore (default). +align_right_cmt_at_col = 0 # unsigned number + +# The span for aligning function prototypes. +# +# 0: Don't align (default). +align_func_proto_span = 0 # unsigned number + +# The threshold for aligning function prototypes. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_proto_thresh = 0 # number + +# Minimum gap between the return type and the function name. +align_func_proto_gap = 0 # unsigned number + +# Whether to align function prototypes on the 'operator' keyword instead of +# what follows. +align_on_operator = false # true/false + +# Whether to mix aligning prototype and variable declarations. If true, +# align_var_def_XXX options are used instead of align_func_proto_XXX options. +align_mix_var_proto = false # true/false + +# Whether to align single-line functions with function prototypes. +# Uses align_func_proto_span. +align_single_line_func = false # true/false + +# Whether to align the open brace of single-line functions. +# Requires align_single_line_func=true. Uses align_func_proto_span. +align_single_line_brace = false # true/false + +# Gap for align_single_line_brace. +align_single_line_brace_gap = 0 # unsigned number + +# (OC) The span for aligning Objective-C message specifications. +# +# 0: Don't align (default). +align_oc_msg_spec_span = 0 # unsigned number + +# Whether to align macros wrapped with a backslash and a newline. This will +# not work right if the macro contains a multi-line comment. +align_nl_cont = false # true/false + +# Whether to align macro functions and variables together. +align_pp_define_together = false # true/false + +# The span for aligning on '#define' bodies. +# +# =0: Don't align (default) +# >0: Number of lines (including comments) between blocks +align_pp_define_span = 0 # unsigned number + +# The minimum space between label and value of a preprocessor define. +align_pp_define_gap = 0 # unsigned number + +# Whether to align lines that start with '<<' with previous '<<'. +# +# Default: true +align_left_shift = true # true/false + +# Whether to align text after 'asm volatile ()' colons. +align_asm_colon = false # true/false + +# (OC) Span for aligning parameters in an Objective-C message call +# on the ':'. +# +# 0: Don't align. +align_oc_msg_colon_span = 0 # unsigned number + +# (OC) Whether to always align with the first parameter, even if it is too +# short. +align_oc_msg_colon_first = false # true/false + +# (OC) Whether to align parameters in an Objective-C '+' or '-' declaration +# on the ':'. +align_oc_decl_colon = false # true/false + +# (OC) Whether to not align parameters in an Objectve-C message call if first +# colon is not on next line of the message call (the same way Xcode does +# aligment) +#align_oc_msg_colon_xcode_like = false # true/false ### not 0.69 + +# +# Comment modification options +# + +# Try to wrap comments at N columns. +cmt_width = 0 # unsigned number + +# How to reflow comments. +# +# 0: No reflowing (apart from the line wrapping due to cmt_width) (default) +# 1: No touching at all +# 2: Full reflow +cmt_reflow_mode = 0 # unsigned number + +# Whether to convert all tabs to spaces in comments. If false, tabs in +# comments are left alone, unless used for indenting. +cmt_convert_tab_to_spaces = false # true/false + +# Whether to apply changes to multi-line comments, including cmt_width, +# keyword substitution and leading chars. +# +# Default: true +cmt_indent_multi = true # true/false + +# Whether to group c-comments that look like they are in a block. +cmt_c_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined c-comment. +cmt_c_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined c-comment. +cmt_c_nl_end = false # true/false + +# Whether to change cpp-comments into c-comments. +cmt_cpp_to_c = false # true/false + +# Whether to group cpp-comments that look like they are in a block. Only +# meaningful if cmt_cpp_to_c=true. +cmt_cpp_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_end = false # true/false + +# Whether to put a star on subsequent comment lines. +cmt_star_cont = false # true/false + +# The number of spaces to insert at the start of subsequent comment lines. +cmt_sp_before_star_cont = 0 # unsigned number + +# The number of spaces to insert after the star on subsequent comment lines. +cmt_sp_after_star_cont = 0 # unsigned number + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length. +# +# Default: true +cmt_multi_check_last = true # true/false + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length AND if the length is +# bigger as the first_len minimum. +# +# Default: 4 +cmt_multi_first_len_minimum = 4 # unsigned number + +# Path to a file that contains text to insert at the beginning of a file if +# the file doesn't start with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_header = "" # string + +# Path to a file that contains text to insert at the end of a file if the +# file doesn't end with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_footer = "" # string + +# Path to a file that contains text to insert before a function definition if +# the function isn't preceded by a C/C++ comment. If the inserted text +# contains '$(function)', '$(javaparam)' or '$(fclass)', these will be +# replaced with, respectively, the name of the function, the javadoc '@param' +# and '@return' stuff, or the name of the class to which the member function +# belongs. +cmt_insert_func_header = "" # string + +# Path to a file that contains text to insert before a class if the class +# isn't preceded by a C/C++ comment. If the inserted text contains '$(class)', +# that will be replaced with the class name. +cmt_insert_class_header = "" # string + +# Path to a file that contains text to insert before an Objective-C message +# specification, if the method isn't preceded by a C/C++ comment. If the +# inserted text contains '$(message)' or '$(javaparam)', these will be +# replaced with, respectively, the name of the function, or the javadoc +# '@param' and '@return' stuff. +cmt_insert_oc_msg_header = "" # string + +# Whether a comment should be inserted if a preprocessor is encountered when +# stepping backwards from a function name. +# +# Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and +# cmt_insert_class_header. +cmt_insert_before_preproc = false # true/false + +# Whether a comment should be inserted if a function is declared inline to a +# class definition. +# +# Applies to cmt_insert_func_header. +# +# Default: true +cmt_insert_before_inlines = true # true/false + +# Whether a comment should be inserted if the function is a class constructor +# or destructor. +# +# Applies to cmt_insert_func_header. +cmt_insert_before_ctor_dtor = false # true/false + +# +# Code modifying options (non-whitespace) +# + +# Add or remove braces on a single-line 'do' statement. +mod_full_brace_do = remove # ignore/add/remove/force + +# Add or remove braces on a single-line 'for' statement. +mod_full_brace_for = remove # ignore/add/remove/force + +# (Pawn) Add or remove braces on a single-line function definition. +mod_full_brace_function = ignore # ignore/add/remove/force + +# Add or remove braces on a single-line 'if' statement. Braces will not be +# removed if the braced statement contains an 'else'. +mod_full_brace_if = add # ignore/add/remove/force + +# Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either +# have, or do not have, braces. If true, braces will be added if any block +# needs braces, and will only be removed if they can be removed from all +# blocks. +# +# Overrides mod_full_brace_if. +mod_full_brace_if_chain = false # true/false + +# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. +# If true, mod_full_brace_if_chain will only remove braces from an 'if' that +# does not have an 'else if' or 'else'. +mod_full_brace_if_chain_only = true # true/false + +# Add or remove braces on single-line 'while' statement. +mod_full_brace_while = remove # ignore/add/remove/force + +# Add or remove braces on single-line 'using ()' statement. +mod_full_brace_using = remove # ignore/add/remove/force + +# Don't remove braces around statements that span N newlines +mod_full_brace_nl = 0 # unsigned number + +# Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks +# which span multiple lines. +# +# Affects: +# mod_full_brace_for +# mod_full_brace_if +# mod_full_brace_if_chain +# mod_full_brace_if_chain_only +# mod_full_brace_while +# mod_full_brace_using +# +# Does not affect: +# mod_full_brace_do +# mod_full_brace_function +mod_full_brace_nl_block_rem_mlcond = false # true/false + +# Add or remove unnecessary parenthesis on 'return' statement. +mod_paren_on_return = add # ignore/add/remove/force + +# (Pawn) Whether to change optional semicolons to real semicolons. +mod_pawn_semicolon = false # true/false + +# Whether to fully parenthesize Boolean expressions in 'while' and 'if' +# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. +mod_full_paren_if_bool = false # true/false + +# Whether to remove superfluous semicolons. +mod_remove_extra_semicolon = false # true/false + +# If a function body exceeds the specified number of newlines and doesn't have +# a comment after the close brace, a comment will be added. +mod_add_long_function_closebrace_comment = 0 # unsigned number + +# If a namespace body exceeds the specified number of newlines and doesn't +# have a comment after the close brace, a comment will be added. +mod_add_long_namespace_closebrace_comment = 0 # unsigned number + +# If a class body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_class_closebrace_comment = 0 # unsigned number + +# If a switch body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_switch_closebrace_comment = 0 # unsigned number + +# If an #ifdef body exceeds the specified number of newlines and doesn't have +# a comment after the #endif, a comment will be added. +mod_add_long_ifdef_endif_comment = 0 # unsigned number + +# If an #ifdef or #else body exceeds the specified number of newlines and +# doesn't have a comment after the #else, a comment will be added. +mod_add_long_ifdef_else_comment = 0 # unsigned number + +# Whether to take care of the case by the mod_sort_xx options. +#mod_sort_case_sensitive = false # true/false ### not 0.69 + +# Whether to sort consecutive single-line 'import' statements. +mod_sort_import = false # true/false + +# (C#) Whether to sort consecutive single-line 'using' statements. +mod_sort_using = false # true/false + +# Whether to sort consecutive single-line '#include' statements (C/C++) and +# '#import' statements (Objective-C). Be aware that this has the potential to +# break your code if your includes/imports have ordering dependencies. +mod_sort_include = false # true/false + +# Whether to prioritize '#include' and '#import' statements that contain +# filename without extension when sorting is enabled. +#mod_sort_incl_import_prioritize_filename = false # true/false ### not 0.69 + +# Whether to prioritize '#include' and '#import' statements that does not +# contain extensions when sorting is enabled. +#mod_sort_incl_import_prioritize_extensionless = false # true/false ### not 0.69 + +# Whether to prioritize '#include' and '#import' statements that contain +# angle over quotes when sorting is enabled. +#mod_sort_incl_import_prioritize_angle_over_quotes = false # true/false ### not 0.69 + +# Whether to ignore file extension in '#include' and '#import' statements +# for sorting comparison. +#mod_sort_incl_import_ignore_extension = false # true/false ### not 0.69 + +# Whether to group '#include' and '#import' statements when sorting is enabled. +#mod_sort_incl_import_grouping_enabled = false # true/false ### not 0.69 + +# Whether to move a 'break' that appears after a fully braced 'case' before +# the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'. +mod_move_case_break = false # true/false + +# Add or remove braces around a fully braced case statement. Will only remove +# braces if there are no variable declarations in the block. +mod_case_brace = ignore # ignore/add/remove/force + +# Whether to remove a void 'return;' that appears as the last statement in a +# function. +mod_remove_empty_return = false # true/false + +# Add or remove the comma after the last value of an enumeration. +mod_enum_last_comma = ignore # ignore/add/remove/force + +# (OC) Whether to organize the properties. If true, properties will be +# rearranged according to the mod_sort_oc_property_*_weight factors. +mod_sort_oc_properties = false # true/false + +# (OC) Weight of a class property modifier. +mod_sort_oc_property_class_weight = 0 # number + +# (OC) Weight of 'atomic' and 'nonatomic'. +mod_sort_oc_property_thread_safe_weight = 0 # number + +# (OC) Weight of 'readwrite' when organizing properties. +mod_sort_oc_property_readwrite_weight = 0 # number + +# (OC) Weight of a reference type specifier ('retain', 'copy', 'assign', +# 'weak', 'strong') when organizing properties. +mod_sort_oc_property_reference_weight = 0 # number + +# (OC) Weight of getter type ('getter=') when organizing properties. +mod_sort_oc_property_getter_weight = 0 # number + +# (OC) Weight of setter type ('setter=') when organizing properties. +mod_sort_oc_property_setter_weight = 0 # number + +# (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified', +# 'null_resettable') when organizing properties. +mod_sort_oc_property_nullability_weight = 0 # number + +# +# Preprocessor options +# + +# Add or remove indentation of preprocessor directives inside #if blocks +# at brace level 0 (file-level). +pp_indent = ignore # ignore/add/remove/force + +# Whether to indent #if/#else/#endif at the brace level. If false, these are +# indented from column 1. +pp_indent_at_level = false # true/false + +# Specifies the number of columns to indent preprocessors per level +# at brace level 0 (file-level). If pp_indent_at_level=false, also specifies +# the number of columns to indent preprocessors per level +# at brace level > 0 (function-level). +# +# Default: 1 +pp_indent_count = 1 # unsigned number + +# Add or remove space after # based on pp_level of #if blocks. +pp_space = ignore # ignore/add/remove/force + +# Sets the number of spaces per level added with pp_space. +pp_space_count = 0 # unsigned number + +# The indent for '#region' and '#endregion' in C# and '#pragma region' in +# C/C++. Negative values decrease indent down to the first column. +pp_indent_region = 0 # number + +# Whether to indent the code between #region and #endregion. +pp_region_indent_code = false # true/false + +# If pp_indent_at_level=true, sets the indent for #if, #else and #endif when +# not at file-level. Negative values decrease indent down to the first column. +# +# =0: Indent preprocessors using output_tab_size +# >0: Column at which all preprocessors will be indented +pp_indent_if = 0 # number + +# Whether to indent the code between #if, #else and #endif. +pp_if_indent_code = false # true/false + +# Whether to indent '#define' at the brace level. If false, these are +# indented from column 1. +pp_define_at_level = false # true/false + +# Whether to ignore the '#define' body while formatting. +pp_ignore_define_body = false # true/false + +# Whether to indent case statements between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the case statements +# directly inside of. +# +# Default: true +pp_indent_case = true # true/false + +# Whether to indent whole function definitions between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the function definition +# is directly inside of. +# +# Default: true +pp_indent_func_def = true # true/false + +# Whether to indent extern C blocks between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the extern block is +# directly inside of. +# +# Default: true +pp_indent_extern = true # true/false + +# Whether to indent braces directly inside #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the braces are directly +# inside of. +# +# Default: true +pp_indent_brace = true # true/false + +# +# Sort includes options +# + +# The regex for include category with priority 0. +include_category_0 = "" # string + +# The regex for include category with priority 1. +include_category_1 = "" # string + +# The regex for include category with priority 2. +include_category_2 = "" # string + +# +# Use or Do not Use options +# + +# true: indent_func_call_param will be used (default) +# false: indent_func_call_param will NOT be used +# +# Default: true +use_indent_func_call_param = true # true/false + +# The value of the indentation for a continuation line is calculated +# differently if the statement is: +# - a declaration: your case with QString fileName ... +# - an assignment: your case with pSettings = new QSettings( ... +# +# At the second case the indentation value might be used twice: +# - at the assignment +# - at the function call (if present) +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indent_continue will be used only once +# false: indent_continue will be used every time (default) +use_indent_continue_only_once = false # true/false + +# The value might be used twice: +# - at the assignment +# - at the opening brace +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indentation will be used only once +# false: indentation will be used every time (default) +indent_cpp_lambda_only_once = false # true/false + +# Whether sp_after_angle takes precedence over sp_inside_fparen. This was the +# historic behavior, but is probably not the desired behavior, so this is off +# by default. +#use_sp_after_angle_always = false # true/false ### not 0.69 + +# Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially, +# this tries to format these so that they match Qt's normalized form (i.e. the +# result of QMetaObject::normalizedSignature), which can slightly improve the +# performance of the QObject::connect call, rather than how they would +# otherwise be formatted. +# +# See options_for_QT.cpp for details. +# +# Default: true +use_options_overriding_for_qt_macros = true # true/false + +# If true: the form feed character is removed from the list +# of whitespace characters. +# See https://en.cppreference.com/w/cpp/string/byte/isspace +#use_form_feed_no_more_as_whitespace_character = false # true/false ### not 0.69 + +# +# Warn levels - 1: error, 2: warning (default), 3: note +# + +# (C#) Warning is given if doing tab-to-\t replacement and we have found one +# in a C# verbatim string literal. +# +# Default: 2 +warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number + +# Limit the number of loops. +# Used by uncrustify.cpp to exit from infinite loop. +# 0: no limit. +#debug_max_number_of_loops = 0 # number ### not 0.69 + +# Set the number of the line to protocol; +# Used in the function prot_the_line if the 2. parameter is zero. +# 0: nothing protocol. +#debug_line_number_to_protocol = 0 # number ### not 0.69 + +# Meaning of the settings: +# Ignore - do not do any changes +# Add - makes sure there is 1 or more space/brace/newline/etc +# Force - makes sure there is exactly 1 space/brace/newline/etc, +# behaves like Add in some contexts +# Remove - removes space/brace/newline/etc +# +# +# - Token(s) can be treated as specific type(s) with the 'set' option: +# `set tokenType tokenString [tokenString...]` +# +# Example: +# `set BOOL __AND__ __OR__` +# +# tokenTypes are defined in src/token_enum.h, use them without the +# 'CT_' prefix: 'CT_BOOL' => 'BOOL' +# +# +# - Token(s) can be treated as type(s) with the 'type' option. +# `type tokenString [tokenString...]` +# +# Example: +# `type int c_uint_8 Rectangle` +# +# This can also be achieved with `set TYPE int c_uint_8 Rectangle` +# +# +# To embed whitespace in tokenStrings use the '\' escape character, or quote +# the tokenStrings. These quotes are supported: "'` +# +# +# - Support for the auto detection of languages through the file ending can be +# added using the 'file_ext' command. +# `file_ext langType langString [langString..]` +# +# Example: +# `file_ext CPP .ch .cxx .cpp.in` +# +# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use +# them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP' +# +# +# - Custom macro-based indentation can be set up using 'macro-open', +# 'macro-else' and 'macro-close'. +# `(macro-open | macro-else | macro-close) tokenString` +# +# Example: +# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP` +# `macro-open BEGIN_MESSAGE_MAP` +# `macro-close END_MESSAGE_MAP` +# +# +# option(s) with 'not default' value: 0 +# diff --git a/doc/dev/developer.txt b/doc/dev/developer.txt index 4032eca3e..077234e54 100644 --- a/doc/dev/developer.txt +++ b/doc/dev/developer.txt @@ -8,9 +8,7 @@ In order to use pkg-config for development purposes, add the following lines to ## Package configuration (pkg-config) on unix-based systems if (NOT WIN32 AND NOT CMAKE_CROSSCOMPILING) - add_subdirectory(doc/dev/pkg-config) # Option A: external tool pkg-config - find_package(PkgConfig) # Option B: internal cmake module for pkg-config integration - pkg_check_modules(GTK3 gtk+-3.0) + add_subdirectory(doc/dev/pkg-config) # external tool pkg-config endif () ToDo: Check for compatibility issues between options A and B. diff --git a/flashloaders/linker.ld b/flashloaders/linker.ld index 4d06433ea..7267fe10f 100644 --- a/flashloaders/linker.ld +++ b/flashloaders/linker.ld @@ -1,9 +1,9 @@ -/*. Entry Point *./ +/* Entry Point */ ENTRY( copy ) -/*. Specify the memory areas .*/ +/* Specify the memory areas */ MEMORY { RAM ( xrw) : ORIGIN = 0x20000000 , LENGTH = 64K -} \ No newline at end of file +} diff --git a/inc/CMakeLists.txt b/inc/CMakeLists.txt new file mode 100644 index 000000000..66af7e33f --- /dev/null +++ b/inc/CMakeLists.txt @@ -0,0 +1,9 @@ +configure_file( + "${PROJECT_SOURCE_DIR}/inc/version.h.in" + "${CMAKE_BINARY_DIR}/inc/version.h" + ) + +file(GLOB STLINK_HEADERS "src/st-link-lib/*.h" "${CMAKE_BINARY_DIR}/inc/version.h") +install(FILES ${STLINK_HEADERS} DESTINATION ${STLINK_INCLUDE_PATH}) +install(FILES ${CMAKE_SOURCE_DIR}/inc/stlink.h DESTINATION ${STLINK_INCLUDE_PATH}) +install(FILES ${CMAKE_SOURCE_DIR}/inc/stm32.h DESTINATION ${STLINK_INCLUDE_PATH}) diff --git a/include/stlink/backend.h b/inc/backend.h similarity index 94% rename from include/stlink/backend.h rename to inc/backend.h index 42d12d4ac..f852da05d 100644 --- a/include/stlink/backend.h +++ b/inc/backend.h @@ -28,7 +28,7 @@ int (*current_mode) (stlink_t * stl); int (*force_debug) (stlink_t *sl); int32_t (*target_voltage) (stlink_t *sl); - int (*set_swdclk) (stlink_t * stl, uint16_t divisor); + int (*set_swdclk) (stlink_t * stl, uint16_t divisor); } stlink_backend_t; -#endif /* STLINK_BACKEND_H_ */ +#endif // STLINK_BACKEND_H_ diff --git a/include/stlink.h b/inc/stlink.h similarity index 84% rename from include/stlink.h rename to inc/stlink.h index c87c6b173..140d68866 100644 --- a/include/stlink.h +++ b/inc/stlink.h @@ -18,11 +18,11 @@ extern "C" { #endif -#define STLINK_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#define STLINK_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) /* Max data transfer size */ // 6kB = max mem32_read block, 8kB sram -//#define Q_BUF_LEN 96 +// #define Q_BUF_LEN 96 #define Q_BUF_LEN (1024 * 100) // STLINK_DEBUG_RESETSYS, etc: @@ -103,16 +103,16 @@ enum target_state { #define S_RESET_ST (1 << 25) /* Map the relevant features, quirks and workaround for specific firmware version of stlink */ -#define STLINK_F_HAS_TRACE (1<<0) -#define STLINK_F_HAS_SWD_SET_FREQ (1<<1) -#define STLINK_F_HAS_JTAG_SET_FREQ (1<<2) -#define STLINK_F_HAS_MEM_16BIT (1<<3) -#define STLINK_F_HAS_GETLASTRWSTATUS2 (1<<4) -#define STLINK_F_HAS_DAP_REG (1<<5) -#define STLINK_F_QUIRK_JTAG_DP_READ (1<<6) -#define STLINK_F_HAS_AP_INIT (1<<7) -#define STLINK_F_HAS_DPBANKSEL (1<<8) -#define STLINK_F_HAS_RW8_512BYTES (1<<9) +#define STLINK_F_HAS_TRACE (1 << 0) +#define STLINK_F_HAS_SWD_SET_FREQ (1 << 1) +#define STLINK_F_HAS_JTAG_SET_FREQ (1 << 2) +#define STLINK_F_HAS_MEM_16BIT (1 << 3) +#define STLINK_F_HAS_GETLASTRWSTATUS2 (1 << 4) +#define STLINK_F_HAS_DAP_REG (1 << 5) +#define STLINK_F_QUIRK_JTAG_DP_READ (1 << 6) +#define STLINK_F_HAS_AP_INIT (1 << 7) +#define STLINK_F_HAS_DPBANKSEL (1 << 8) +#define STLINK_F_HAS_RW8_512BYTES (1 << 9) #define C_BUF_LEN 32 @@ -146,8 +146,8 @@ struct stlink_reg { typedef uint32_t stm32_addr_t; typedef struct flash_loader { -stm32_addr_t loader_addr; // loader sram addr -stm32_addr_t buf_addr; // buffer sram address + stm32_addr_t loader_addr; // loader sram addr + stm32_addr_t buf_addr; // buffer sram address } flash_loader_t; typedef struct _cortex_m3_cpuid_ { @@ -183,16 +183,16 @@ enum transport_type { }; typedef struct _stlink stlink_t; - + #include struct _stlink { struct _stlink_backend *backend; void *backend_data; - // Room for the command header + // room for the command header unsigned char c_buf[C_BUF_LEN]; - // Data transferred from or to device + // data transferred from or to device unsigned char q_buf[Q_BUF_LEN]; int q_len; @@ -205,28 +205,29 @@ struct _stlink { char serial[STLINK_SERIAL_MAX_SIZE]; int serial_size; - int freq; // set by stlink_open_usb(), values: STLINK_SWDCLK_xxx_DIVISOR + int freq; // set by stlink_open_usb(), values: STLINK_SWDCLK_xxx_DIVISOR enum stlink_flash_type flash_type; // stlink_chipid_params.flash_type, set by stlink_load_device_params(), values: STLINK_FLASH_TYPE_xxx bool has_dual_bank; - stm32_addr_t flash_base; // STM32_FLASH_BASE, set by stlink_load_device_params() - size_t flash_size; // calculated by stlink_load_device_params() - size_t flash_pgsz; // stlink_chipid_params.flash_pagesize, set by stlink_load_device_params() + stm32_addr_t flash_base; // STM32_FLASH_BASE, set by stlink_load_device_params() + size_t flash_size; // calculated by stlink_load_device_params() + size_t flash_pgsz; // stlink_chipid_params.flash_pagesize, set by stlink_load_device_params() /* sram settings */ - stm32_addr_t sram_base; // STM32_SRAM_BASE, set by stlink_load_device_params() - size_t sram_size; // stlink_chipid_params.sram_size, set by stlink_load_device_params() + stm32_addr_t sram_base; // STM32_SRAM_BASE, set by stlink_load_device_params() + size_t sram_size; // stlink_chipid_params.sram_size, set by stlink_load_device_params() - /* option settings */ + /* option settings */ stm32_addr_t option_base; size_t option_size; // bootloader - // sys_base and sys_size are not used by the tools, but are only there to download the bootloader code (see tests/sg.c) - stm32_addr_t sys_base; // stlink_chipid_params.bootrom_base, set by stlink_load_device_params() - size_t sys_size; // stlink_chipid_params.bootrom_size, set by stlink_load_device_params() + // sys_base and sys_size are not used by the tools, but are only there to download the bootloader code + // (see tests/sg.c) + stm32_addr_t sys_base; // stlink_chipid_params.bootrom_base, set by stlink_load_device_params() + size_t sys_size; // stlink_chipid_params.bootrom_size, set by stlink_load_device_params() struct stlink_version_ version; }; @@ -306,4 +307,4 @@ int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr } #endif -#endif /* STLINK_H */ +#endif // STLINK_H diff --git a/include/stm32.h b/inc/stm32.h similarity index 82% rename from include/stm32.h rename to inc/stm32.h index c71718653..36c14ee23 100644 --- a/include/stm32.h +++ b/inc/stm32.h @@ -1,17 +1,17 @@ /* - * File: stm32.h + * File: stm32.h * - * STM32 specific defines + * STM32-specific defines */ #ifndef STM32_H #define STM32_H -// cortex core ids +/* Cortex core ids */ #define STM32VL_CORE_ID 0x1ba01477 #define STM32F7_CORE_ID 0x5ba02477 -// Constant STM32 memory map figures +/* Constant STM32 memory map figures */ #define STM32_FLASH_BASE ((uint32_t)0x08000000) #define STM32_SRAM_BASE ((uint32_t)0x20000000) #define STM32_G0_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800) @@ -21,4 +21,4 @@ #define STM32_L4_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800) #define STM32_L1_OPTION_BYTES_BASE ((uint32_t)0x1FF80000) -#endif /* STM32_H */ +#endif // STM32_H diff --git a/include/stlink/version.h.in b/inc/version.h.in similarity index 90% rename from include/stlink/version.h.in rename to inc/version.h.in index 4ce2a5cac..66159e0e5 100644 --- a/include/stlink/version.h.in +++ b/inc/version.h.in @@ -6,4 +6,4 @@ #define STLINK_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define STLINK_VERSION_PATCH @PROJECT_VERSION_PATCH@ -#endif /* STLINK_VERSION_ */ +#endif // STLINK_VERSION_H_ diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt deleted file mode 100644 index 6cf397659..000000000 --- a/include/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -configure_file( - "${PROJECT_SOURCE_DIR}/include/stlink/version.h.in" - "${CMAKE_BINARY_DIR}/include/stlink/version.h" - ) - -file(GLOB STLINK_HEADERS "stlink/*.h" "${CMAKE_BINARY_DIR}/include/stlink/*.h") -install(FILES ${CMAKE_SOURCE_DIR}/include/stlink.h DESTINATION ${STLINK_INCLUDE_PATH}) -install(FILES ${CMAKE_SOURCE_DIR}/include/stm32.h DESTINATION ${STLINK_INCLUDE_PATH}) -install(FILES ${STLINK_HEADERS} DESTINATION ${STLINK_INCLUDE_PATH}/stlink) diff --git a/include/stlink/chipid.h b/include/stlink/chipid.h deleted file mode 100644 index 98164a8fc..000000000 --- a/include/stlink/chipid.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef STLINK_CHIPID_H_ -#define STLINK_CHIPID_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Chip IDs are explained in the appropriate programming manual for the - * DBGMCU_IDCODE register (0xE0042000) - * stm32 chipids, only lower 12 bits.. - */ -enum stlink_stm32_chipids { - STLINK_CHIPID_UNKNOWN = 0x000, - - STLINK_CHIPID_STM32_F1_MEDIUM = 0x410, - STLINK_CHIPID_STM32_F2 = 0x411, - STLINK_CHIPID_STM32_F1_LOW = 0x412, - STLINK_CHIPID_STM32_F4 = 0x413, - STLINK_CHIPID_STM32_F1_HIGH = 0x414, - STLINK_CHIPID_STM32_L4 = 0x415, - STLINK_CHIPID_STM32_L1_MEDIUM = 0x416, - STLINK_CHIPID_STM32_L0 = 0x417, - STLINK_CHIPID_STM32_F1_CONN = 0x418, - STLINK_CHIPID_STM32_F4_HD = 0x419, - STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW = 0x420, - STLINK_CHIPID_STM32_F446 = 0x421, - STLINK_CHIPID_STM32_F3 = 0x422, - STLINK_CHIPID_STM32_F4_LP = 0x423, - STLINK_CHIPID_STM32_L0_CAT2 = 0x425, - STLINK_CHIPID_STM32_L1_MEDIUM_PLUS = 0x427, /* assigned to some L1 "Medium-plus" chips */ - STLINK_CHIPID_STM32_F1_VL_HIGH = 0x428, - STLINK_CHIPID_STM32_L1_CAT2 = 0x429, - STLINK_CHIPID_STM32_F1_XL = 0x430, - STLINK_CHIPID_STM32_F411RE = 0x431, - STLINK_CHIPID_STM32_F37x = 0x432, - STLINK_CHIPID_STM32_F4_DE = 0x433, - STLINK_CHIPID_STM32_F4_DSI = 0x434, - STLINK_CHIPID_STM32_L43X = 0x435, /* covers STM32L43xxx and STM32L44xxx devices */ - STLINK_CHIPID_STM32_L496X = 0x461, /* covers STM32L496xx and STM32L4A6xx devices */ - STLINK_CHIPID_STM32_L46X = 0x462, /* covers STM32L45xxx and STM32L46xxx devices */ - STLINK_CHIPID_STM32_L41X = 0x464, /* covers STM32L41xxx and STM32L42xxx devices */ - STLINK_CHIPID_STM32_L1_HIGH = 0x436, /* assigned to some L1 chips called "Medium-Plus" and to some called "High" */ - STLINK_CHIPID_STM32_L152_RE = 0x437, - STLINK_CHIPID_STM32_F334 = 0x438, - STLINK_CHIPID_STM32_F3_SMALL = 0x439, - STLINK_CHIPID_STM32_F0 = 0x440, - STLINK_CHIPID_STM32_F412 = 0x441, - STLINK_CHIPID_STM32_F09X = 0x442, - STLINK_CHIPID_STM32_F0_SMALL = 0x444, - STLINK_CHIPID_STM32_F04 = 0x445, - STLINK_CHIPID_STM32_F303_HIGH = 0x446, - STLINK_CHIPID_STM32_L0_CAT5 = 0x447, - STLINK_CHIPID_STM32_F0_CAN = 0x448, - STLINK_CHIPID_STM32_F7 = 0x449, /* This ID is found on the NucleoF746ZG board */ - STLINK_CHIPID_STM32_F7XXXX = 0x451, - STLINK_CHIPID_STM32_F72XXX = 0x452, /* This ID is found on the NucleoF722ZE board */ - STLINK_CHIPID_STM32_L011 = 0x457, - STLINK_CHIPID_STM32_F410 = 0x458, - STLINK_CHIPID_STM32_G0_CAT2 = 0x460, /* G070/G071/081 */ - STLINK_CHIPID_STM32_F413 = 0x463, - STLINK_CHIPID_STM32_G0_CAT1 = 0x466, /* G030/G031/041 */ - STLINK_CHIPID_STM32_G4_CAT2 = 0x468, /* See: RM 0440 s46.6.1 "MCU device ID code" */ - STLINK_CHIPID_STM32_G4_CAT3 = 0x469, - STLINK_CHIPID_STM32_L4RX = 0x470, /* taken from the STM32L4R9I-DISCO board */ - STLINK_CHIPID_STM32_WB55 = 0x495 -}; - -/** - * Chipid parameters - */ -struct stlink_chipid_params { - uint32_t chip_id; - char *description; - enum stlink_flash_type flash_type; - bool has_dual_bank; - uint32_t flash_size_reg; - uint32_t flash_pagesize; - uint32_t sram_size; - uint32_t bootrom_base; - uint32_t bootrom_size; - uint32_t option_base; - uint32_t option_size; -}; - -const struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chipid); - -#ifdef __cplusplus -} -#endif - -#endif /* STLINK_CHIPID_H_ */ diff --git a/include/stlink/reg.h b/include/stlink/reg.h deleted file mode 100644 index 765ac9525..000000000 --- a/include/stlink/reg.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STLINK_REG_H_ -#define STLINK_REG_H_ - -#define STLINK_REG_CM3_CPUID 0xE000ED00 -#define STLINK_REG_CM3_FP_CTRL 0xE0002000 -#define STLINK_REG_CM3_FP_COMP0 0xE0002008 - -/* Cortex™-M3 Technical Reference Manual */ -/* Debug Halting Control and Status Register */ -#define STLINK_REG_DHCSR 0xe000edf0 -#define STLINK_REG_DHCSR_DBGKEY 0xa05f0000 -#define STLINK_REG_DCRSR 0xe000edf4 -#define STLINK_REG_DCRDR 0xe000edf8 - -/* Application Interrupt and Reset Control Register */ -#define STLINK_REG_AIRCR 0xe000ed0c -#define STLINK_REG_AIRCR_VECTKEY 0x05fa0000 -#define STLINK_REG_AIRCR_SYSRESETREQ 0x00000004 - -#endif /* STLINK_REG_H_ */ diff --git a/src/chipid.c b/src/chipid.c deleted file mode 100644 index fcc1c55eb..000000000 --- a/src/chipid.c +++ /dev/null @@ -1,637 +0,0 @@ -#include -#include - -static const struct stlink_chipid_params devices[] = { - { - //RM0410 document was used to find these paramaters - .chip_id = STLINK_CHIPID_STM32_F7XXXX, - .description = "F76xxx", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1ff0f442, // section 45.2 - .flash_pagesize = 0x800, // No flash pages - .sram_size = 0x80000, // "SRAM" byte size in hex from - .bootrom_base = 0x00200000, //! "System memory" starting address from - .bootrom_size = 0xEDC0 //! @todo "System memory" byte size in hex from - }, - { - //RM0385 and DS10916 document was used to find these paramaters - .chip_id = STLINK_CHIPID_STM32_F7, - .description = "F7xx", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1ff0f442, // section 41.2 - .flash_pagesize = 0x800, // No flash pages - .sram_size = 0x50000, // "SRAM" byte size in hex from DS Fig 18 - .bootrom_base = 0x00100000, // "System memory" starting address from DS Fig 18 - .bootrom_size = 0xEDC0 // "System memory" byte size in hex from DS Fig 18 - }, - { - //RM0431 and DS document was used to find these paramaters - .chip_id = STLINK_CHIPID_STM32_F72XXX, - .description = "F72x/F73x", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1ff07a22, // section 35.2 - .flash_pagesize = 0x800, // No flash pages - .sram_size = 0x40000, // "SRAM" byte size in hex from DS Fig 24 - .bootrom_base = 0x00100000, // "System memory" starting address from DS Fig 24 - .bootrom_size = 0xEDC0 // "System memory" byte size in hex from DS Fig 24 - }, - { // table 2, PM0063 - .chip_id = STLINK_CHIPID_STM32_F1_MEDIUM, - .description = "F1xx Medium-density", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7e0, - .flash_pagesize = 0x400, - .sram_size = 0x5000, - .bootrom_base = 0x1ffff000, - .bootrom_size = 0x800 - }, - { // table 1, PM0059 - .chip_id = STLINK_CHIPID_STM32_F2, - .description = "F2xx", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1fff7a22, /* As in RM0033 Rev 5*/ - .flash_pagesize = 0x20000, - .sram_size = 0x20000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800, - .option_base = 0x1FFFC000, - .option_size = 4, - }, - { // PM0063 - .chip_id = STLINK_CHIPID_STM32_F1_LOW, - .description = "F1 Low-density device", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7e0, - .flash_pagesize = 0x400, - .sram_size = 0x2800, - .bootrom_base = 0x1ffff000, - .bootrom_size = 0x800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F4, - .description = "F4xx", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, /* As in rm0090 since Rev 2*/ - .flash_pagesize = 0x4000, - .sram_size = 0x30000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F4_DSI, - .description = "F46x/F47x", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, /* As in rm0090 since Rev 2*/ - .flash_pagesize = 0x4000, - .sram_size = 0x40000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F4_HD, - .description = "F42x/F43x", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, /* As in rm0090 since Rev 2*/ - .flash_pagesize = 0x4000, - .sram_size = 0x40000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F4_LP, - .description = "F4xx (low power)", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, - .flash_pagesize = 0x4000, - .sram_size = 0x10000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F411RE, - .description = "stm32f411re", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, - .flash_pagesize = 0x4000, - .sram_size = 0x20000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F4_DE, - .description = "F4xx (Dynamic Efficency)", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, - .flash_pagesize = 0x4000, - .sram_size = 0x18000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F1_HIGH, - .description = "F1xx High-density", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7e0, - .flash_pagesize = 0x800, - .sram_size = 0x10000, - .bootrom_base = 0x1ffff000, - .bootrom_size = 0x800 - }, - { - // This ignores the EEPROM! (and uses the page erase size, - // not the sector write protection...) - .chip_id = STLINK_CHIPID_STM32_L1_MEDIUM, - .description = "L1xx Medium-density", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff8004c, - .flash_pagesize = 0x100, - .sram_size = 0x4000, - .bootrom_base = 0x1ff00000, - .bootrom_size = 0x1000 - }, - { - .chip_id = STLINK_CHIPID_STM32_L1_CAT2, - .description = "L1xx Cat.2", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff8004c, - .flash_pagesize = 0x100, - .sram_size = 0x8000, - .bootrom_base = 0x1ff00000, - .bootrom_size = 0x1000 - }, - { - .chip_id = STLINK_CHIPID_STM32_L1_MEDIUM_PLUS, - .description = "L1xx Medium-Plus-density", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff800cc, - .flash_pagesize = 0x100, - .sram_size = 0x8000,/*Not completely clear if there are some with 48K*/ - .bootrom_base = 0x1ff00000, - .bootrom_size = 0x1000 - }, - { - .chip_id = STLINK_CHIPID_STM32_L1_HIGH, - .description = "L1xx High-density", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff800cc, - .flash_pagesize = 0x100, - .sram_size = 0xC000, /*Not completely clear if there are some with 32K*/ - .bootrom_base = 0x1ff00000, - .bootrom_size = 0x1000, - .option_base = STM32_L1_OPTION_BYTES_BASE, - .option_size = 8, - }, - { - .chip_id = STLINK_CHIPID_STM32_L152_RE, - .description = "L152RE", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff800cc, - .flash_pagesize = 0x100, - .sram_size = 0x14000, /*Not completely clear if there are some with 32K*/ - .bootrom_base = 0x1ff00000, - .bootrom_size = 0x1000 - }, - { - .chip_id = STLINK_CHIPID_STM32_F1_CONN, - .description = "F1 Connectivity line", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7e0, - .flash_pagesize = 0x800, - .sram_size = 0x10000, - .bootrom_base = 0x1fffb000, - .bootrom_size = 0x4800 - }, - {//Low and Medium density VL have same chipid. RM0041 25.6.1 - .chip_id = STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW, - .description = "F1xx Value Line", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7e0, - .flash_pagesize = 0x400, - .sram_size = 0x2000,//0x1000 for low density devices - .bootrom_base = 0x1ffff000, - .bootrom_size = 0x800 - }, - { - // STM32F446x family. Support based on DM00135183.pdf (RM0390) document. - .chip_id = STLINK_CHIPID_STM32_F446, - .description = "F446", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1fff7a22, - .flash_pagesize = 0x20000, - .sram_size = 0x20000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800, - .option_base = 0x1FFFC000, - .option_size = 4, - }, - { - // STM32F410 MCUs. Support based on DM00180366.pdf (RM0401) document. - .chip_id = STLINK_CHIPID_STM32_F410, - .description = "F410", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1fff7a22, - .flash_pagesize = 0x4000, - .sram_size = 0x8000, - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7800 - }, - { - // This is STK32F303VCT6 device from STM32 F3 Discovery board. - // Support based on DM00043574.pdf (RM0316) document. - .chip_id = STLINK_CHIPID_STM32_F3, - .description = "F3xx", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, - .flash_pagesize = 0x800, - .sram_size = 0xa000, - .bootrom_base = 0x1ffff000, - .bootrom_size = 0x800 - }, - { - // This is STK32F373VCT6 device from STM32 F373 eval board - // Support based on 303 above (37x and 30x have same memory map) - .chip_id = STLINK_CHIPID_STM32_F37x, - .description = "F3xx", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, - .flash_pagesize = 0x800, - .sram_size = 0xa000, - .bootrom_base = 0x1ffff000, - .bootrom_size = 0x800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F1_VL_HIGH, - .description = "F1xx High-density value line", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7e0, - .flash_pagesize = 0x800, - .sram_size = 0x8000, - .bootrom_base = 0x1ffff000, - .bootrom_size = 0x800 - }, - { - .chip_id = STLINK_CHIPID_STM32_F1_XL, - .description = "F1xx XL-density", - .flash_type = STLINK_FLASH_TYPE_F1_XL, - .flash_size_reg = 0x1ffff7e0, - .flash_pagesize = 0x800, - .sram_size = 0x18000, - .bootrom_base = 0x1fffe000, - .bootrom_size = 0x1800 - }, - { - //Use this as an example for mapping future chips: - //RM0091 document was used to find these paramaters - .chip_id = STLINK_CHIPID_STM32_F0_CAN, - .description = "F07x", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x800, // Page sizes listed in Table 4 - .sram_size = 0x4000, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffC800, // "System memory" starting address from Table 2 - .bootrom_size = 0x3000 // "System memory" byte size in hex from Table 2 - }, - { - //Use this as an example for mapping future chips: - //RM0091 document was used to find these paramaters - .chip_id = STLINK_CHIPID_STM32_F0, - .description = "F0xx", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x400, // Page sizes listed in Table 4 - .sram_size = 0x2000, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 - .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2 - }, - { - // RM0402 document was used to find these parameters - // Table 4. - .chip_id = STLINK_CHIPID_STM32_F412, - .description = "F412", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, // "Flash size data register" (pg1135) - .flash_pagesize = 0x4000, // Table 5. Flash module organization ? - .sram_size = 0x40000, // "SRAM" byte size in hex from Table 4 - .bootrom_base = 0x1FFF0000, // "System memory" starting address from Table 4 - .bootrom_size = 0x7800 // "System memory" byte size in hex from Table 4 - }, - { - // RM0430 DocID029473 Rev 2 document was used to find these parameters - // Figure 2, Table 4, Table 5, Section 35.2 - .chip_id = STLINK_CHIPID_STM32_F413, - .description = "F413", - .flash_type = STLINK_FLASH_TYPE_F4, - .flash_size_reg = 0x1FFF7A22, // "Flash size data register" Section 35.2 - .flash_pagesize = 0x4000, // Table 5. Flash module organization (variable sector sizes, but 0x4000 is smallest) - .sram_size = 0x50000, // "SRAM" byte size in hex from Figure 2 (Table 4 only says 0x40000) - .bootrom_base = 0x1FFF0000, // "System memory" starting address from Table 4 - .bootrom_size = 0x7800 // "System memory" byte size in hex from Table 4 - }, - { - .chip_id = STLINK_CHIPID_STM32_F09X, - .description = "F09X", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x800, // Page sizes listed in Table 4 (pg 56) - .sram_size = 0x8000, // "SRAM" byte size in hex from Table 2 (pg 50) - .bootrom_base = 0x1fffd800, // "System memory" starting address from Table 2 - .bootrom_size = 0x2000 // "System memory" byte size in hex from Table 2 - }, - { - //Use this as an example for mapping future chips: - //RM0091 document was used to find these paramaters - .chip_id = STLINK_CHIPID_STM32_F04, - .description = "F04x", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x400, // Page sizes listed in Table 4 - .sram_size = 0x1800, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 - .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2 - }, - { - //Use this as an example for mapping future chips: - //RM0091 document was used to find these paramaters - .chip_id = STLINK_CHIPID_STM32_F0_SMALL, - .description = "F0xx small", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) - .flash_pagesize = 0x400, // Page sizes listed in Table 4 - .sram_size = 0x1000, // "SRAM" byte size in hex from Table 2 - .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 - .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2 - }, - { - // STM32F30x - .chip_id = STLINK_CHIPID_STM32_F3_SMALL, - .description = "F3xx small", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, - .flash_pagesize = 0x800, - .sram_size = 0xa000, - .bootrom_base = 0x1fffd800, - .bootrom_size = 0x2000 - }, - { - // STM32L0x - // RM0367,RM0377 documents was used to find these parameters - .chip_id = STLINK_CHIPID_STM32_L0, - .description = "L0x3", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff8007c, - .flash_pagesize = 0x80, - .sram_size = 0x2000, - .bootrom_base = 0x1ff0000, - .bootrom_size = 0x1000, - .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32L0x Category 5 - // RM0367,RM0377 documents was used to find these parameters - .chip_id = STLINK_CHIPID_STM32_L0_CAT5, - .description = "L0xx Category 5", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff8007c, - .flash_pagesize = 0x80, - .sram_size = 0x5000, - .bootrom_base = 0x1ff0000, - .bootrom_size = 0x2000, - .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32L0x Category 2 - // RM0367,RM0377 documents was used to find these parameters - .chip_id = STLINK_CHIPID_STM32_L0_CAT2, - .description = "L0xx Category 2", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff8007c, - .flash_pagesize = 0x80, - .sram_size = 0x2000, - .bootrom_base = 0x1ff0000, - .bootrom_size = 0x1000, - .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32F334, STM32F303x6/8, and STM32F328 - // From RM0364 and RM0316 - .chip_id = STLINK_CHIPID_STM32_F334, - .description = "F334 medium density", // (RM0316 sec 33.6.1) - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, - .flash_pagesize = 0x800, - .sram_size = 0x3000, - .bootrom_base = 0x1fffd800, - .bootrom_size = 0x2000 - }, - { - // This is STK32F303RET6 device from STM32 F3 Nucelo board. - // Support based on DM00043574.pdf (RM0316) document rev 5. - .chip_id = STLINK_CHIPID_STM32_F303_HIGH, - .description = "F303 high density", - .flash_type = STLINK_FLASH_TYPE_F0, - .flash_size_reg = 0x1ffff7cc, // 34.2.1 Flash size data register - .flash_pagesize = 0x800, // 4.2.1 Flash memory organization - .sram_size = 0x10000, // 3.3 Embedded SRAM - .bootrom_base = 0x1fffd800, // 3.3.2 / Table 4 System Memory - .bootrom_size = 0x2000 - }, - { - // STM32L4x6 - // From RM0351. - .chip_id = STLINK_CHIPID_STM32_L4, - .description = "L4xx", - .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1FFF75e0, // "Flash size data register" (sec 45.2, page 1671) - .flash_pagesize = 0x800, // 2K (sec 3.2, page 78; also appears in sec 3.3.1 and tables 4-6 on pages 79-81) - // SRAM1 is "up to" 96k in the standard Cortex-M memory map; - // SRAM2 is 32k mapped at at 0x10000000 (sec 2.3, page 73 for - // sizes; table 2, page 74 for SRAM2 location) - .sram_size = 0x18000, - .bootrom_base = 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) - .bootrom_size = 0x7000, // 28k (per bank), same source as base - .option_base = STM32_L4_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32L4RX - // From DM00310109.pdf - .chip_id = STLINK_CHIPID_STM32_L4RX, - .description = "L4Rx", - .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 52.2, page 2049) - .flash_pagesize = 0x1000, // 4k, section 3.3, pg 97 - .sram_size = 0xa0000, // 192k (SRAM1) + 64k SRAM2 + 384k SRAM3 = 640k, or 0xA0000 - .bootrom_base = 0x1fff0000, // 3.3.1, pg 99 - .bootrom_size = 0x7000 // 28k (per bank), same source as base (pg 99) - }, - { - // STLINK_CHIPID_STM32_L41X - // From RM0394 Rev 4 and DS12469 Rev 5 - .chip_id = STLINK_CHIPID_STM32_L41X, - .description = "L41x", - .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (RM0394, sec 47.2, page 1586) - .flash_pagesize = 0x800, // 2K (DS12469, sec 3.4, page 17) - // SRAM1 is 32k at 0x20000000 - // SRAM2 is 8k at 0x10000000 and 0x20008000 (DS12469, sec 3.5, page 18) - .sram_size = 0xa000, // 40K (DS12469, sec 3.5, page 18) - .bootrom_base = 0x1fff0000, // System Memory (RM0394, sec 3.3.1, table 8) - .bootrom_size = 0x7000 // 28k, same source as base - }, - { - // STLINK_CHIPID_STM32_L43X - // From RM0392. - .chip_id = STLINK_CHIPID_STM32_L43X, - .description = "L43x/L44x", - .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 43.2, page 1410) - .flash_pagesize = 0x800, // 2K (sec 3.2, page 74; also appears in sec 3.3.1 and tables 7-8 on pages 75-76) - // SRAM1 is "up to" 64k in the standard Cortex-M memory map; - // SRAM2 is 16k mapped at 0x10000000 (sec 2.3, page 73 for - // sizes; table 2, page 74 for SRAM2 location) - .sram_size = 0xc000, - .bootrom_base = 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) - .bootrom_size = 0x7000, // 28k (per bank), same source as base - .option_base = STM32_L4_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STLINK_CHIPID_STM32_L496X - // Support based on en.DM00083560.pdf (RM0351) document rev 5. - .chip_id = STLINK_CHIPID_STM32_L496X, - .description = "L496x/L4A6x", - .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 49.2, page 1809) - .flash_pagesize = 0x800, // Page erase (2 Kbyte) (sec 3.2, page 93) - // SRAM1 is 256k at 0x20000000 - // SRAM2 is 64k at 0x20040000 (sec 2.2.1, fig 2, page 74) - .sram_size = 0x40000, // Embedded SRAM (sec 2.4, page 84) - .bootrom_base = 0x1fff0000, // System Memory (Bank 1) (sec 3.3.1) - .bootrom_size = 0x7000, // 28k (per bank), same source as base - .option_base = STM32_L4_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STLINK_CHIPID_STM32_L46X - // From RM0394 (updated version of RM0392?). - .chip_id = STLINK_CHIPID_STM32_L46X, - .description = "L45x/46x", - .flash_type = STLINK_FLASH_TYPE_L4, - .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 45.2, page 1463) - .flash_pagesize = 0x800, // 2K (sec 3.2, page 73; also appears in sec 3.3.1 and tables 7 on pages 73-74) - // SRAM1 is 128k at 0x20000000; - // SRAM2 is 32k mapped at 0x10000000 (sec 2.4.2, table 3-4, page 68, also fig 2 on page 63) - .sram_size = 0x20000, - .bootrom_base = 0x1fff0000, // Tables 6, pages 71-72 (Bank 1 system memory, also fig 2 on page 63) - .bootrom_size = 0x7000 // 28k (per bank), same source as base - }, - { - // STM32L011 - .chip_id = STLINK_CHIPID_STM32_L011, - .description = "L011", - .flash_type = STLINK_FLASH_TYPE_L0, - .flash_size_reg = 0x1ff8007c, - .flash_pagesize = 0x80, - .sram_size = 0x2000, - .bootrom_base = 0x1ff00000, - .bootrom_size = 0x2000 - }, - { - // STM32G030/031/041 (from RM0454 & RM0444) - .chip_id = STLINK_CHIPID_STM32_G0_CAT1, - .description = "G030/G031/G041", - .flash_type = STLINK_FLASH_TYPE_G0, - .flash_size_reg = 0x1FFF75E0, // Section 38.2 - .flash_pagesize = 0x800, // 2K (sec 3.2) - .sram_size = 0x2000, // 8K (sec 2.3) - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x2000, // 8K (sec 2.2.2 table 3) - .option_base = STM32_G0_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32G071/081 (from RM0444) - .chip_id = STLINK_CHIPID_STM32_G0_CAT2, - .description = "G070/G071/G081", - .flash_type = STLINK_FLASH_TYPE_G0, - .flash_size_reg = 0x1FFF75E0, // Section 38.2 - .flash_pagesize = 0x800, // 2K (sec 3.2) - .sram_size = 0x9000, // 36K (sec 2.3) - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7000, // 28K (sec 2.2.2 table 2) - .option_base = STM32_G0_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32G431/441 (from RM0440) - .chip_id = STLINK_CHIPID_STM32_G4_CAT2, - .description = "G4 Category-2", - .flash_type = STLINK_FLASH_TYPE_G4, - .flash_size_reg = 0x1FFF75E0, // Section 47.2 - .flash_pagesize = 0x800, // 2K (sec 3.3.1) - // SRAM1 is 16k at 0x20000000 - // SRAM2 is 6k at 0x20014000 - // SRAM3/CCM is 10k at 0x10000000, aliased at 0x20018000 - .sram_size = 0x8000, // 32K (sec 2.4) - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7000, // 28K (table 2) - .option_base = STM32_G4_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32G471/473/474/483/484 (from RM0440) - .chip_id = STLINK_CHIPID_STM32_G4_CAT3, - .description = "G4 Category-3", - .flash_type = STLINK_FLASH_TYPE_G4, - .has_dual_bank = true, - .flash_size_reg = 0x1FFF75E0, // Section 47.2 - .flash_pagesize = 0x800, // 2K (sec 3.3.1) - // SRAM1 is 80k at 0x20000000 - // SRAM2 is 16k at 0x20014000 - // SRAM3/CCM is 32k at 0x10000000, aliased at 0x20018000 - .sram_size = 0x18000, // 128K (sec 2.4) - .bootrom_base = 0x1fff0000, - .bootrom_size = 0x7000, // 28K (table 2) - .option_base = STM32_G4_OPTION_BYTES_BASE, - .option_size = 4, - }, - { - // STM32WB55 (from RM0434) - .chip_id = STLINK_CHIPID_STM32_WB55, - .description = "WB55", - .flash_type = STLINK_FLASH_TYPE_WB, - .flash_size_reg = 0x1FFF75E0, - .flash_pagesize = 0x1000, // 4K - .sram_size = 0x40000, - .bootrom_base = 0x1fff0000, // See the memory map - .bootrom_size = 0x7000 - }, - { - // unknown - .chip_id = STLINK_CHIPID_UNKNOWN, - .description = "unknown device", - .flash_type = STLINK_FLASH_TYPE_UNKNOWN, - .flash_size_reg = 0x0, - .flash_pagesize = 0x0, - .sram_size = 0x0, - .bootrom_base = 0x0, - .bootrom_size = 0x0 - }, - }; - -const struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chipid) -{ - const struct stlink_chipid_params *params = NULL; - - for (size_t n = 0; n < STLINK_ARRAY_SIZE(devices); n++) { - if (devices[n].chip_id == chipid) { - params = &devices[n]; - break; - } - } - - return params; -} diff --git a/src/common.c b/src/common.c index e8f7cebc6..361a24dbf 100644 --- a/src/common.c +++ b/src/common.c @@ -12,9 +12,14 @@ #include #include -#include "mmap.h" -#include "logging.h" -#include "md5.h" +#include +#include + +#ifdef STLINK_HAVE_SYS_MMAN_H +#include +#else +#include +#endif #ifndef O_BINARY #define O_BINARY 0 @@ -186,37 +191,39 @@ // WB Flash status register. #define STM32WB_FLASH_SR_BSY (16) /* FLASH_SR Busy */ -//32L4 register base is at FLASH_REGS_ADDR (0x40022000) +// 32L4 register base is at FLASH_REGS_ADDR (0x40022000) #define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08) #define STM32L4_FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x0C) #define STM32L4_FLASH_SR (FLASH_REGS_ADDR + 0x10) #define STM32L4_FLASH_CR (FLASH_REGS_ADDR + 0x14) #define STM32L4_FLASH_OPTR (FLASH_REGS_ADDR + 0x20) -#define STM32L4_FLASH_SR_BSY 16 -#define STM32L4_FLASH_SR_ERRMASK 0x3f8 /* SR [9:3] */ - -#define STM32L4_FLASH_CR_LOCK 31 /* Lock control register */ -#define STM32L4_FLASH_CR_OPTLOCK 30 /* Lock option bytes */ -#define STM32L4_FLASH_CR_PG 0 /* Program */ -#define STM32L4_FLASH_CR_PER 1 /* Page erase */ -#define STM32L4_FLASH_CR_MER1 2 /* Bank 1 erase */ -#define STM32L4_FLASH_CR_MER2 15 /* Bank 2 erase */ -#define STM32L4_FLASH_CR_STRT 16 /* Start command */ -#define STM32L4_FLASH_CR_OPTSTRT 17 /* Start writing option bytes */ -#define STM32L4_FLASH_CR_BKER 11 /* Bank select for page erase */ -#define STM32L4_FLASH_CR_PNB 3 /* Page number (8 bits) */ -#define STM32L4_FLASH_CR_OBL_LAUNCH 27 /* Option bytes reload */ +#define STM32L4_FLASH_SR_BSY 16 +#define STM32L4_FLASH_SR_ERRMASK 0x3f8 /* SR [9:3] */ + +#define STM32L4_FLASH_CR_LOCK 31 /* Lock control register */ +#define STM32L4_FLASH_CR_OPTLOCK 30 /* Lock option bytes */ +#define STM32L4_FLASH_CR_PG 0 /* Program */ +#define STM32L4_FLASH_CR_PER 1 /* Page erase */ +#define STM32L4_FLASH_CR_MER1 2 /* Bank 1 erase */ +#define STM32L4_FLASH_CR_MER2 15 /* Bank 2 erase */ +#define STM32L4_FLASH_CR_STRT 16 /* Start command */ +#define STM32L4_FLASH_CR_OPTSTRT 17 /* Start writing option bytes */ +#define STM32L4_FLASH_CR_BKER 11 /* Bank select for page erase */ +#define STM32L4_FLASH_CR_PNB 3 /* Page number (8 bits) */ +#define STM32L4_FLASH_CR_OBL_LAUNCH 27 /* Option bytes reload */ // Bits requesting flash operations (useful when we want to clear them) -#define STM32L4_FLASH_CR_OPBITS \ - (uint32_t)((1lu< le (don't swap) - buf[0] = ((unsigned char*) &ui)[0]; - buf[1] = ((unsigned char*) &ui)[1]; - buf[2] = ((unsigned char*) &ui)[2]; - buf[3] = ((unsigned char*) &ui)[3]; + buf[0] = ((unsigned char*)&ui)[0]; + buf[1] = ((unsigned char*)&ui)[1]; + buf[2] = ((unsigned char*)&ui)[2]; + buf[3] = ((unsigned char*)&ui)[3]; } else { - buf[0] = ((unsigned char*) &ui)[3]; - buf[1] = ((unsigned char*) &ui)[2]; - buf[2] = ((unsigned char*) &ui)[1]; - buf[3] = ((unsigned char*) &ui)[0]; + buf[0] = ((unsigned char*)&ui)[3]; + buf[1] = ((unsigned char*)&ui)[2]; + buf[2] = ((unsigned char*)&ui)[1]; + buf[3] = ((unsigned char*)&ui)[0]; } } void write_uint16(unsigned char* buf, uint16_t ui) { if (!is_bigendian()) { // le -> le (don't swap) - buf[0] = ((unsigned char*) &ui)[0]; - buf[1] = ((unsigned char*) &ui)[1]; + buf[0] = ((unsigned char*)&ui)[0]; + buf[1] = ((unsigned char*)&ui)[1]; } else { - buf[0] = ((unsigned char*) &ui)[1]; - buf[1] = ((unsigned char*) &ui)[0]; + buf[0] = ((unsigned char*)&ui)[1]; + buf[1] = ((unsigned char*)&ui)[0]; } } uint32_t read_uint32(const unsigned char *c, const int pt) { uint32_t ui; - char *p = (char *) &ui; + char *p = (char *)&ui; if (!is_bigendian()) { // le -> le (don't swap) p[0] = c[pt + 0]; @@ -310,49 +317,51 @@ uint32_t read_uint32(const unsigned char *c, const int pt) { p[2] = c[pt + 1]; p[3] = c[pt + 0]; } - return ui; + + return(ui); } static uint32_t get_stm32l0_flash_base(stlink_t *sl) { switch (sl->chip_id) { - case STLINK_CHIPID_STM32_L1_CAT2: - case STLINK_CHIPID_STM32_L1_MEDIUM: - case STLINK_CHIPID_STM32_L1_MEDIUM_PLUS: - case STLINK_CHIPID_STM32_L1_HIGH: - return STM32L1_FLASH_REGS_ADDR; - default: - return STM32L0_FLASH_REGS_ADDR; + case STLINK_CHIPID_STM32_L1_CAT2: + case STLINK_CHIPID_STM32_L1_MEDIUM: + case STLINK_CHIPID_STM32_L1_MEDIUM_PLUS: + case STLINK_CHIPID_STM32_L1_HIGH: + return(STM32L1_FLASH_REGS_ADDR); + default: + return(STM32L0_FLASH_REGS_ADDR); } } static uint32_t __attribute__((unused)) read_flash_rdp(stlink_t *sl) { uint32_t rdp; stlink_read_debug32(sl, FLASH_WRPR, &rdp); - return rdp & 0xff; + return(rdp & 0xff); } static inline uint32_t read_flash_cr(stlink_t *sl) { uint32_t reg, res; - if (sl->flash_type == STLINK_FLASH_TYPE_F4) + if (sl->flash_type == STLINK_FLASH_TYPE_F4) { reg = FLASH_F4_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_L4) + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { reg = STM32L4_FLASH_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { reg = STM32Gx_FLASH_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_WB) + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { reg = STM32WB_FLASH_CR; - else + } else { reg = FLASH_CR; + } stlink_read_debug32(sl, reg, &res); #if DEBUG_FLASH fprintf(stdout, "CR:0x%x\n", res); #endif - return res; + return(res); } static inline uint32_t read_flash_cr2(stlink_t *sl) { @@ -361,7 +370,7 @@ static inline uint32_t read_flash_cr2(stlink_t *sl) { #if DEBUG_FLASH fprintf(stdout, "CR2:0x%x\n", res); #endif - return res; + return(res); } static inline unsigned int is_flash_locked(stlink_t *sl) { @@ -371,7 +380,7 @@ static inline unsigned int is_flash_locked(stlink_t *sl) { uint32_t n; if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { cr_reg = FLASH_CR; cr_lock_shift = FLASH_CR_LOCK; } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { @@ -392,25 +401,24 @@ static inline unsigned int is_flash_locked(stlink_t *sl) { cr_lock_shift = STM32WB_FLASH_CR_LOCK; } else { ELOG("unsupported flash method, abort\n"); - return -1; + return(-1); } stlink_read_debug32(sl, cr_reg, &n); - return n & (1u << cr_lock_shift); + return(n & (1u << cr_lock_shift)); } static void unlock_flash(stlink_t *sl) { uint32_t key_reg; uint32_t flash_key1 = FLASH_KEY1; uint32_t flash_key2 = FLASH_KEY2; - /* the unlock sequence consists of 2 write cycles where - 2 key values are written to the FLASH_KEYR register. - an invalid sequence results in a definitive lock of - the FPEC block until next reset. - */ + /* The unlock sequence consists of 2 write cycles where 2 key values are written + * to the FLASH_KEYR register. + * An invalid sequence results in a definitive lock of the FPEC block until next reset. + */ if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { key_reg = FLASH_KEYR; } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { key_reg = FLASH_F4_KEYR; @@ -421,7 +429,7 @@ static void unlock_flash(stlink_t *sl) { } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { key_reg = STM32L4_FLASH_KEYR; } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { + sl->flash_type == STLINK_FLASH_TYPE_G4) { key_reg = STM32Gx_FLASH_KEYR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { key_reg = STM32WB_FLASH_KEYR; @@ -443,20 +451,22 @@ static void unlock_flash(stlink_t *sl) { static int unlock_flash_if(stlink_t *sl) { if (is_flash_locked(sl)) { unlock_flash(sl); + if (is_flash_locked(sl)) { WLOG("Failed to unlock flash!\n"); - return -1; + return(-1); } } + DLOG("Successfully unlocked flash\n"); - return 0; + return(0); } static void lock_flash(stlink_t *sl) { uint32_t cr_lock_shift, cr_reg, n; if (sl->flash_type == STLINK_FLASH_TYPE_F0 || - sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { cr_reg = FLASH_CR; cr_lock_shift = FLASH_CR_LOCK; } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { @@ -496,43 +506,45 @@ static bool is_flash_option_locked(stlink_t *sl) { uint32_t n; switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - case STLINK_FLASH_TYPE_F1_XL: - optcr_reg = FLASH_CR; - optlock_shift = FLASH_CR_OPTWRE; - active_bit_level = 0; /* bit is "option write enable", not lock */ - break; - case STLINK_FLASH_TYPE_F4: - optcr_reg = FLASH_F4_OPTCR; - optlock_shift = FLASH_F4_OPTCR_LOCK; - break; - case STLINK_FLASH_TYPE_L0: - optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; - optlock_shift = STM32L0_FLASH_OPTLOCK; - break; - case STLINK_FLASH_TYPE_L4: - optcr_reg = STM32L4_FLASH_CR; - optlock_shift = STM32L4_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - optcr_reg = STM32Gx_FLASH_CR; - optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_WB: - optcr_reg = STM32WB_FLASH_CR; - optlock_shift = STM32WB_FLASH_CR_OPTLOCK; - break; - default: - ELOG("unsupported flash method, abort\n"); - return -1; + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + optcr_reg = FLASH_CR; + optlock_shift = FLASH_CR_OPTWRE; + active_bit_level = 0; // bit is "option write enable", not lock + break; + case STLINK_FLASH_TYPE_F4: + optcr_reg = FLASH_F4_OPTCR; + optlock_shift = FLASH_F4_OPTCR_LOCK; + break; + case STLINK_FLASH_TYPE_L0: + optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; + optlock_shift = STM32L0_FLASH_OPTLOCK; + break; + case STLINK_FLASH_TYPE_L4: + optcr_reg = STM32L4_FLASH_CR; + optlock_shift = STM32L4_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + optcr_reg = STM32Gx_FLASH_CR; + optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_WB: + optcr_reg = STM32WB_FLASH_CR; + optlock_shift = STM32WB_FLASH_CR_OPTLOCK; + break; + default: + ELOG("unsupported flash method, abort\n"); + return(-1); } stlink_read_debug32(sl, optcr_reg, &n); - if (active_bit_level == 0) - return !(n & (1u << optlock_shift)); - return n & (1u << optlock_shift); + if (active_bit_level == 0) { + return(!(n & (1u << optlock_shift))); + } + + return(n & (1u << optlock_shift)); } @@ -541,104 +553,106 @@ static int lock_flash_option(stlink_t *sl) { int active_bit_level = 1; switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - case STLINK_FLASH_TYPE_F1_XL: - optcr_reg = FLASH_CR; - optlock_shift = FLASH_CR_OPTWRE; - active_bit_level = 0; - break; - case STLINK_FLASH_TYPE_F4: - optcr_reg = FLASH_F4_OPTCR; - optlock_shift = FLASH_F4_OPTCR_LOCK; - break; - case STLINK_FLASH_TYPE_L0: - optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; - optlock_shift = STM32L0_FLASH_OPTLOCK; - break; - case STLINK_FLASH_TYPE_L4: - optcr_reg = STM32L4_FLASH_CR; - optlock_shift = STM32L4_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - optcr_reg = STM32Gx_FLASH_CR; - optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; - break; - case STLINK_FLASH_TYPE_WB: - optcr_reg = STM32WB_FLASH_CR; - optlock_shift = STM32WB_FLASH_CR_OPTLOCK; - break; - default: - ELOG("unsupported flash method, abort\n"); - return -1; + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + optcr_reg = FLASH_CR; + optlock_shift = FLASH_CR_OPTWRE; + active_bit_level = 0; + break; + case STLINK_FLASH_TYPE_F4: + optcr_reg = FLASH_F4_OPTCR; + optlock_shift = FLASH_F4_OPTCR_LOCK; + break; + case STLINK_FLASH_TYPE_L0: + optcr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF; + optlock_shift = STM32L0_FLASH_OPTLOCK; + break; + case STLINK_FLASH_TYPE_L4: + optcr_reg = STM32L4_FLASH_CR; + optlock_shift = STM32L4_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + optcr_reg = STM32Gx_FLASH_CR; + optlock_shift = STM32Gx_FLASH_CR_OPTLOCK; + break; + case STLINK_FLASH_TYPE_WB: + optcr_reg = STM32WB_FLASH_CR; + optlock_shift = STM32WB_FLASH_CR_OPTLOCK; + break; + default: + ELOG("unsupported flash method, abort\n"); + return(-1); } stlink_read_debug32(sl, optcr_reg, &n); - if (active_bit_level == 0) + + if (active_bit_level == 0) { n &= ~(1u << optlock_shift); - else + } else { n |= (1u << optlock_shift); - stlink_write_debug32(sl, optcr_reg, n); + } - return 0; + stlink_write_debug32(sl, optcr_reg, n); + return(0); } -static int unlock_flash_option(stlink_t *sl) -{ +static int unlock_flash_option(stlink_t *sl) { uint32_t optkey_reg; uint32_t optkey1 = FLASH_OPTKEY1; uint32_t optkey2 = FLASH_OPTKEY2; switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - case STLINK_FLASH_TYPE_F1_XL: - optkey_reg = FLASH_OPTKEYR; - optkey1 = FLASH_F0_OPTKEY1; - optkey2 = FLASH_F0_OPTKEY2; - break; - case STLINK_FLASH_TYPE_F4: - optkey_reg = FLASH_F4_OPT_KEYR; - break; - case STLINK_FLASH_TYPE_L0: - optkey_reg = get_stm32l0_flash_base(sl) + FLASH_OPTKEYR_OFF; - optkey1 = FLASH_L0_OPTKEY1; - optkey2 = FLASH_L0_OPTKEY2; - break; - case STLINK_FLASH_TYPE_L4: - optkey_reg = STM32L4_FLASH_OPTKEYR; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - optkey_reg = STM32Gx_FLASH_OPTKEYR; - break; - case STLINK_FLASH_TYPE_WB: - optkey_reg = STM32WB_FLASH_OPT_KEYR; - break; + case STLINK_FLASH_TYPE_F0: + case STLINK_FLASH_TYPE_F1_XL: + optkey_reg = FLASH_OPTKEYR; + optkey1 = FLASH_F0_OPTKEY1; + optkey2 = FLASH_F0_OPTKEY2; + break; + case STLINK_FLASH_TYPE_F4: + optkey_reg = FLASH_F4_OPT_KEYR; + break; + case STLINK_FLASH_TYPE_L0: + optkey_reg = get_stm32l0_flash_base(sl) + FLASH_OPTKEYR_OFF; + optkey1 = FLASH_L0_OPTKEY1; + optkey2 = FLASH_L0_OPTKEY2; + break; + case STLINK_FLASH_TYPE_L4: + optkey_reg = STM32L4_FLASH_OPTKEYR; + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + optkey_reg = STM32Gx_FLASH_OPTKEYR; + break; + case STLINK_FLASH_TYPE_WB: + optkey_reg = STM32WB_FLASH_OPT_KEYR; + break; - default: - ELOG("unsupported flash method, abort\n"); - return -1; + default: + ELOG("unsupported flash method, abort\n"); + return(-1); } stlink_write_debug32(sl, optkey_reg, optkey1); stlink_write_debug32(sl, optkey_reg, optkey2); - - return 0; + return(0); } static int unlock_flash_option_if(stlink_t *sl) { if (is_flash_option_locked(sl)) { if (unlock_flash_option(sl)) { ELOG("Could not unlock flash option!\n"); - return -1; + return(-1); } + if (is_flash_option_locked(sl)) { ELOG("Failed to unlock flash option!\n"); - return -1; + return(-1); } } + DLOG("Successfully unlocked flash option\n"); - return 0; + return(0); } static void set_flash_cr_pg(stlink_t *sl) { @@ -648,11 +662,11 @@ static void set_flash_cr_pg(stlink_t *sl) { if (sl->flash_type == STLINK_FLASH_TYPE_F4) { cr_reg = FLASH_F4_CR; - x |= 1 << FLASH_CR_PG; + x |= (1 << FLASH_CR_PG); } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { cr_reg = STM32L4_FLASH_CR; x &= ~STM32L4_FLASH_CR_OPBITS; - x |= 1 << STM32L4_FLASH_CR_PG; + x |= (1 << STM32L4_FLASH_CR_PG); } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_G4) { cr_reg = STM32Gx_FLASH_CR; @@ -662,7 +676,7 @@ static void set_flash_cr_pg(stlink_t *sl) { x |= (1 << FLASH_CR_PG); } else { cr_reg = FLASH_CR; - x = 1 << FLASH_CR_PG; + x = (1 << FLASH_CR_PG); } stlink_write_debug32(sl, cr_reg, x); @@ -671,17 +685,18 @@ static void set_flash_cr_pg(stlink_t *sl) { static void clear_flash_cr_pg(stlink_t *sl) { uint32_t cr_reg, n; - if (sl->flash_type == STLINK_FLASH_TYPE_F4) + if (sl->flash_type == STLINK_FLASH_TYPE_F4) { cr_reg = FLASH_F4_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_L4) + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { cr_reg = STM32L4_FLASH_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) + } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { cr_reg = STM32Gx_FLASH_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_WB) + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; - else + } else { cr_reg = FLASH_CR; + } n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG); stlink_write_debug32(sl, cr_reg, n); @@ -691,12 +706,13 @@ static void set_flash_cr_per(stlink_t *sl) { uint32_t cr_reg, val; if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) + sl->flash_type == STLINK_FLASH_TYPE_G4) { cr_reg = STM32Gx_FLASH_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_WB) + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; - else + } else { cr_reg = FLASH_CR; + } stlink_read_debug32(sl, cr_reg, &val); val |= (1 << FLASH_CR_PER); @@ -704,7 +720,7 @@ static void set_flash_cr_per(stlink_t *sl) { } static void set_flash_cr2_per(stlink_t *sl) { - const uint32_t n = 1 << FLASH_CR_PER; + const uint32_t n = (1 << FLASH_CR_PER); stlink_write_debug32(sl, FLASH_CR2, n); } @@ -712,12 +728,13 @@ static void clear_flash_cr_per(stlink_t *sl) { uint32_t cr_reg; if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) + sl->flash_type == STLINK_FLASH_TYPE_G4) { cr_reg = STM32Gx_FLASH_CR; - else if (sl->flash_type == STLINK_FLASH_TYPE_WB) + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; - else + } else { cr_reg = FLASH_CR; + } const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PER); stlink_write_debug32(sl, cr_reg, n); @@ -728,19 +745,21 @@ static void set_flash_cr_mer(stlink_t *sl, bool v) { if (sl->flash_type == STLINK_FLASH_TYPE_F4) { cr_reg = FLASH_F4_CR; - cr_mer = 1 << FLASH_CR_MER; - cr_pg = 1 << FLASH_CR_PG; + cr_mer = (1 << FLASH_CR_MER); + cr_pg = (1 << FLASH_CR_PG); } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { cr_reg = STM32L4_FLASH_CR; cr_mer = (1 << STM32L4_FLASH_CR_MER1) | (1 << STM32L4_FLASH_CR_MER2); - cr_pg = 1 << STM32L4_FLASH_CR_PG; + cr_pg = (1 << STM32L4_FLASH_CR_PG); } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_G4) { cr_reg = STM32Gx_FLASH_CR; cr_mer = (1 << STM32Gx_FLASH_CR_MER1); + if (sl->has_dual_bank) { cr_mer |= (1 << STM32Gx_FLASH_CR_MER2); } + cr_pg = (1 << FLASH_CR_PG); } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; @@ -748,35 +767,41 @@ static void set_flash_cr_mer(stlink_t *sl, bool v) { cr_pg = (1 << FLASH_CR_PG); } else { cr_reg = FLASH_CR; - cr_mer = 1 << FLASH_CR_MER; - cr_pg = 1 << FLASH_CR_PG; + cr_mer = (1 << FLASH_CR_MER); + cr_pg = (1 << FLASH_CR_PG); } stlink_read_debug32(sl, cr_reg, &val); + if (val & cr_pg) { - /* STM32F030 will drop MER bit if PG was set */ + // STM32F030 will drop MER bit if PG was set val &= ~cr_pg; stlink_write_debug32(sl, cr_reg, val); } - if (v) + if (v) { val |= cr_mer; - else + } else { val &= ~cr_mer; + } + stlink_write_debug32(sl, cr_reg, val); } static void set_flash_cr2_mer(stlink_t *sl, bool v) { - const uint32_t cr_pg = 1 << FLASH_CR_PER; - const uint32_t cr_mer = 1 << FLASH_CR_MER; + const uint32_t cr_pg = (1 << FLASH_CR_PER); + const uint32_t cr_mer = (1 << FLASH_CR_MER); uint32_t val; stlink_read_debug32(sl, FLASH_CR2, &val); val &= ~cr_pg; - if (v) + + if (v) { val |= cr_mer; - else + } else { val &= ~cr_mer; + } + stlink_write_debug32(sl, FLASH_CR2, val); } @@ -785,13 +810,13 @@ static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) { if (sl->flash_type == STLINK_FLASH_TYPE_F4) { cr_reg = FLASH_F4_CR; - cr_mer = 1 << FLASH_CR_MER; + cr_mer = (1 << FLASH_CR_MER); } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { cr_reg = STM32L4_FLASH_CR; cr_mer = (1 << STM32L4_FLASH_CR_MER1) | (1 << STM32L4_FLASH_CR_MER2); } else { cr_reg = FLASH_CR; - cr_mer = 1 << FLASH_CR_MER; + cr_mer = (1 << FLASH_CR_MER); } stlink_read_debug32(sl, cr_reg, &val); @@ -804,20 +829,20 @@ static void set_flash_cr_strt(stlink_t *sl) { if (sl->flash_type == STLINK_FLASH_TYPE_F4) { cr_reg = FLASH_F4_CR; - cr_strt = 1 << FLASH_F4_CR_STRT; + cr_strt = (1 << FLASH_F4_CR_STRT); } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { cr_reg = STM32L4_FLASH_CR; - cr_strt = 1 << STM32L4_FLASH_CR_STRT; + cr_strt = (1 << STM32L4_FLASH_CR_STRT); } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_G4) { cr_reg = STM32Gx_FLASH_CR; - cr_strt = 1 << STM32Gx_FLASH_CR_STRT; + cr_strt = (1 << STM32Gx_FLASH_CR_STRT); } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; - cr_strt = 1 << STM32WB_FLASH_CR_STRT; + cr_strt = (1 << STM32WB_FLASH_CR_STRT); } else { cr_reg = FLASH_CR; - cr_strt = 1 << FLASH_CR_STRT; + cr_strt = (1 << FLASH_CR_STRT); } stlink_read_debug32(sl, cr_reg, &val); @@ -836,7 +861,8 @@ static void set_flash_cr2_strt(stlink_t *sl) { static inline uint32_t read_flash_sr(stlink_t *sl) { uint32_t res, sr_reg; - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { sr_reg = FLASH_SR; } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { sr_reg = get_stm32l0_flash_base(sl) + FLASH_SR_OFF; @@ -845,44 +871,45 @@ static inline uint32_t read_flash_sr(stlink_t *sl) { } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { sr_reg = STM32L4_FLASH_SR; } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { + sl->flash_type == STLINK_FLASH_TYPE_G4) { sr_reg = STM32Gx_FLASH_SR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { sr_reg = STM32WB_FLASH_SR; } else { ELOG("unsupported flash method, abort"); - return -1; + return(-1); } stlink_read_debug32(sl, sr_reg, &res); - - return res; + return(res); } static inline uint32_t read_flash_sr2(stlink_t *sl) { uint32_t res; stlink_read_debug32(sl, FLASH_SR2, &res); - return res; + return(res); } static inline unsigned int is_flash_busy(stlink_t *sl) { uint32_t sr_busy_shift; unsigned int res; - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || (sl->flash_type == STLINK_FLASH_TYPE_F0) || (sl->flash_type == STLINK_FLASH_TYPE_L0)) { + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_L0)) { sr_busy_shift = FLASH_SR_BSY; } else if (sl->flash_type == STLINK_FLASH_TYPE_F4) { sr_busy_shift = FLASH_F4_SR_BSY; } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { sr_busy_shift = STM32L4_FLASH_SR_BSY; } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { + sl->flash_type == STLINK_FLASH_TYPE_G4) { sr_busy_shift = STM32Gx_FLASH_SR_BSY; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { sr_busy_shift = STM32WB_FLASH_SR_BSY; } else { ELOG("unsupported flash method, abort"); - return -1; + return(-1); } res = read_flash_sr(sl) & (1 << sr_busy_shift); @@ -891,11 +918,11 @@ static inline unsigned int is_flash_busy(stlink_t *sl) { res |= read_flash_sr2(sl) & (1 << sr_busy_shift); } - return res; + return(res); } static void wait_flash_busy(stlink_t *sl) { - /* todo: add some delays here */ + // TODO: add some delays here while (is_flash_busy(sl)) ; } @@ -904,44 +931,48 @@ static void wait_flash_busy_progress(stlink_t *sl) { int i = 0; fprintf(stdout, "Mass erasing"); fflush(stdout); + while (is_flash_busy(sl)) { usleep(10000); i++; + if (i % 100 == 0) { fprintf(stdout, "."); fflush(stdout); } } + fprintf(stdout, "\n"); } static int check_flash_error(stlink_t *sl) { uint32_t res = 0; + switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F0: - res = read_flash_sr(sl) & FLASH_SR_ERROR_MASK; - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - res = read_flash_sr(sl) & STM32Gx_FLASH_SR_ERROR_MASK; - break; - case STLINK_FLASH_TYPE_L0: - res = read_flash_sr(sl) & STM32L0_FLASH_SR_ERROR_MASK; - default: - break; + case STLINK_FLASH_TYPE_F0: + res = read_flash_sr(sl) & FLASH_SR_ERROR_MASK; + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + res = read_flash_sr(sl) & STM32Gx_FLASH_SR_ERROR_MASK; + break; + case STLINK_FLASH_TYPE_L0: + res = read_flash_sr(sl) & STM32L0_FLASH_SR_ERROR_MASK; + default: + break; } if (res) { ELOG("Flash programming error : %#010x\n", res); - return -1; + return(-1); } - return 0; + return(0); } static inline unsigned int is_flash_eop(stlink_t *sl) { - return read_flash_sr(sl) & (1 << FLASH_SR_EOP); + return(read_flash_sr(sl) & (1 << FLASH_SR_EOP)); } static void __attribute__((unused)) clear_flash_sr_eop(stlink_t *sl) { @@ -950,7 +981,7 @@ static void __attribute__((unused)) clear_flash_sr_eop(stlink_t *sl) { } static void __attribute__((unused)) wait_flash_eop(stlink_t *sl) { - /* todo: add some delays here */ + // TODO: add some delays here while (is_flash_eop(sl) == 0) ; } @@ -986,12 +1017,12 @@ static inline void write_flash_cr_snb(stlink_t *sl, uint32_t n) { } static inline void write_flash_cr_bker_pnb(stlink_t *sl, uint32_t n) { - stlink_write_debug32(sl, STM32L4_FLASH_SR, 0xFFFFFFFF & ~(1<backend->close(sl); free(sl); } @@ -1015,26 +1049,28 @@ int stlink_exit_debug_mode(stlink_t *sl) { DLOG("*** stlink_exit_debug_mode ***\n"); ret = stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY); - if (ret == -1) - return ret; - return sl->backend->exit_debug_mode(sl); + if (ret == -1) { + return(ret); + } + + return(sl->backend->exit_debug_mode(sl)); } int stlink_enter_swd_mode(stlink_t *sl) { DLOG("*** stlink_enter_swd_mode ***\n"); - return sl->backend->enter_swd_mode(sl); + return(sl->backend->enter_swd_mode(sl)); } // Force the core into the debug mode -> halted state. int stlink_force_debug(stlink_t *sl) { DLOG("*** stlink_force_debug_mode ***\n"); - return sl->backend->force_debug(sl); + return(sl->backend->force_debug(sl)); } int stlink_exit_dfu_mode(stlink_t *sl) { DLOG("*** stlink_exit_dfu_mode ***\n"); - return sl->backend->exit_dfu_mode(sl); + return(sl->backend->exit_dfu_mode(sl)); } int stlink_core_id(stlink_t *sl) { @@ -1042,14 +1078,18 @@ int stlink_core_id(stlink_t *sl) { DLOG("*** stlink_core_id ***\n"); ret = sl->backend->core_id(sl); + if (ret == -1) { ELOG("Failed to read core_id\n"); - return ret; + return(ret); } - if (sl->verbose > 2) + + if (sl->verbose > 2) { stlink_print_data(sl); + } + DLOG("core_id = 0x%08x\n", sl->core_id); - return ret; + return(ret); } // stlink_chip_id() is called by stlink_load_device_params() @@ -1058,13 +1098,17 @@ int stlink_chip_id(stlink_t *sl, uint32_t *chip_id) { int ret; ret = stlink_read_debug32(sl, 0xE0042000, chip_id); - if (ret == -1) - return ret; - if (*chip_id == 0) - ret = stlink_read_debug32(sl, 0x40015800, chip_id); //Try Corex M0 DBGMCU_IDCODE register address + if (ret == -1) { + return(ret); + } + + if (*chip_id == 0) { + // Try Corex M0 DBGMCU_IDCODE register address + ret = stlink_read_debug32(sl, 0x40015800, chip_id); + } - return ret; + return(ret); } /** @@ -1080,23 +1124,24 @@ int stlink_cpu_id(stlink_t *sl, cortex_m3_cpuid_t *cpuid) { cpuid->variant = 0; cpuid->part = 0; cpuid->revision = 0; - return -1; + return(-1); } + cpuid->implementer_id = (raw >> 24) & 0x7f; cpuid->variant = (raw >> 20) & 0xf; cpuid->part = (raw >> 4) & 0xfff; cpuid->revision = raw & 0xf; - return 0; + return(0); } /** - * reads and decodes the flash parameters, as dynamically as possible + * Reads and decodes the flash parameters, as dynamically as possible * @param sl * @return 0 for success, or -1 for unsupported core type. */ int stlink_load_device_params(stlink_t *sl) { - // This seems to normally work so is unnecessary info for a normal - // user. Demoted to debug. -- REW + // This seems to normally work so is unnecessary info for a normal user. + // Demoted to debug. -- REW DLOG("Loading device parameters....\n"); const struct stlink_chipid_params *params = NULL; stlink_core_id(sl); @@ -1105,43 +1150,50 @@ int stlink_load_device_params(stlink_t *sl) { stlink_chip_id(sl, &chip_id); sl->chip_id = chip_id & 0xfff; - /* Fix chip_id for F4 rev A errata , Read CPU ID, as CoreID is the same for F2/F4*/ + + // Fix chip_id for F4 rev A errata , Read CPU ID, as CoreID is the same for F2/F4 if (sl->chip_id == 0x411) { uint32_t cpuid; stlink_read_debug32(sl, 0xE000ED00, &cpuid); - if ((cpuid & 0xfff0) == 0xc240) + + if ((cpuid & 0xfff0) == 0xc240) { sl->chip_id = 0x413; + } } params = stlink_chipid_get_params(sl->chip_id); + if (params == NULL) { WLOG("unknown chip id! %#x\n", chip_id); - return -1; + return(-1); } if (params->flash_type == STLINK_FLASH_TYPE_UNKNOWN) { WLOG("Invalid flash type, please check device declaration\n"); sl->flash_size = 0; - return 0; + return(0); } // These are fixed... sl->flash_base = STM32_FLASH_BASE; sl->sram_base = STM32_SRAM_BASE; - stlink_read_debug32(sl,(params->flash_size_reg) & ~3, &flash_size); - if (params->flash_size_reg & 2) - flash_size = flash_size >>16; + stlink_read_debug32(sl, (params->flash_size_reg) & ~3, &flash_size); + + if (params->flash_size_reg & 2) { + flash_size = flash_size >> 16; + } + flash_size = flash_size & 0xffff; if ((sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM || sl->chip_id == STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW || - sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM_PLUS) && ( flash_size == 0 )) { - sl->flash_size = 128 * 1024; + sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM_PLUS) && (flash_size == 0)) { + sl->flash_size = 128 * 1024; } else if (sl->chip_id == STLINK_CHIPID_STM32_L1_CAT2) { sl->flash_size = (flash_size & 0xff) * 1024; } else if ((sl->chip_id & 0xFFF) == STLINK_CHIPID_STM32_L1_HIGH) { // 0 is 384k and 1 is 256k - if ( flash_size == 0){ + if (flash_size == 0) { sl->flash_size = 384 * 1024; } else { sl->flash_size = 256 * 1024; @@ -1159,54 +1211,53 @@ int stlink_load_device_params(stlink_t *sl) { sl->option_base = params->option_base; sl->option_size = params->option_size; - //medium and low devices have the same chipid. ram size depends on flash size. - //STM32F100xx datasheet Doc ID 16455 Table 2 - if (sl->chip_id == STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW && sl->flash_size < 64 * 1024){ + // medium and low devices have the same chipid. ram size depends on flash size. + // STM32F100xx datasheet Doc ID 16455 Table 2 + if (sl->chip_id == STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW && sl->flash_size < 64 * 1024) { sl->sram_size = 0x1000; } if (sl->chip_id == STLINK_CHIPID_STM32_G4_CAT3) { uint32_t flash_optr; stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, &flash_optr); - if (!(flash_optr & (1 << STM32G4_FLASH_OPTR_DBANK))) { - sl->flash_pgsz <<= 1; - } + + if (!(flash_optr & (1 << STM32G4_FLASH_OPTR_DBANK))) { sl->flash_pgsz <<= 1; } } #if 0 // Old code -- REW ILOG("Device connected is: %s, id %#x\n", params->description, chip_id); - // TODO make note of variable page size here..... + // TODO: make note of variable page size here..... ILOG("SRAM size: %#x bytes (%d KiB), Flash: %#x bytes (%d KiB) in pages of %u bytes\n", - sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024, - (unsigned int)sl->flash_pgsz); + sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024, + (unsigned int)sl->flash_pgsz); #else ILOG("%s: %zd KiB SRAM, %zd KiB flash in at least %zd %s pages.\n", - params->description, sl->sram_size / 1024, sl->flash_size / 1024, - (sl->flash_pgsz < 1024)? sl->flash_pgsz : sl->flash_pgsz/1024, - (sl->flash_pgsz < 1024)? "byte" : "KiB"); + params->description, sl->sram_size / 1024, sl->flash_size / 1024, + (sl->flash_pgsz < 1024) ? sl->flash_pgsz : sl->flash_pgsz / 1024, + (sl->flash_pgsz < 1024) ? "byte" : "KiB"); #endif - return 0; + return(0); } int stlink_reset(stlink_t *sl) { DLOG("*** stlink_reset ***\n"); - return sl->backend->reset(sl); + return(sl->backend->reset(sl)); } int stlink_jtag_reset(stlink_t *sl, int value) { DLOG("*** stlink_jtag_reset ***\n"); - return sl->backend->jtag_reset(sl, value); + return(sl->backend->jtag_reset(sl, value)); } int stlink_run(stlink_t *sl) { DLOG("*** stlink_run ***\n"); - return sl->backend->run(sl); + return(sl->backend->run(sl)); } int stlink_set_swdclk(stlink_t *sl, uint16_t divisor) { DLOG("*** set_swdclk ***\n"); - return sl->backend->set_swdclk(sl, divisor); + return(sl->backend->set_swdclk(sl, divisor)); } int stlink_status(stlink_t *sl) { @@ -1215,8 +1266,7 @@ int stlink_status(stlink_t *sl) { DLOG("*** stlink_status ***\n"); ret = sl->backend->status(sl); stlink_core_stat(sl); - - return ret; + return(ret); } /** @@ -1226,13 +1276,14 @@ int stlink_status(stlink_t *sl) { */ void _parse_version(stlink_t *sl, stlink_version_t *slv) { sl->version.flags = 0; + if (sl->version.stlink_v < 3) { - uint32_t b0 = sl->q_buf[0]; //lsb + uint32_t b0 = sl->q_buf[0]; // lsb uint32_t b1 = sl->q_buf[1]; uint32_t b2 = sl->q_buf[2]; uint32_t b3 = sl->q_buf[3]; uint32_t b4 = sl->q_buf[4]; - uint32_t b5 = sl->q_buf[5]; //msb + uint32_t b5 = sl->q_buf[5]; // msb // b0 b1 || b2 b3 | b4 b5 // 4b | 6b | 6b || 2B | 2B @@ -1243,14 +1294,17 @@ void _parse_version(stlink_t *sl, stlink_version_t *slv) { slv->swim_v = b1 & 0x3f; slv->st_vid = (b3 << 8) | b2; slv->stlink_pid = (b5 << 8) | b4; - /* ST-LINK/V1 from J11 switch to api-v2 (and support SWD) */ - if (slv->stlink_v == 1) - slv->jtag_api = slv->jtag_v > 11? STLINK_JTAG_API_V2 : STLINK_JTAG_API_V1; - else { + + // ST-LINK/V1 from J11 switch to api-v2 (and support SWD) + if (slv->stlink_v == 1) { + slv->jtag_api = slv->jtag_v > 11 ? STLINK_JTAG_API_V2 : STLINK_JTAG_API_V1; + } else { slv->jtag_api = STLINK_JTAG_API_V2; - /* preferred API to get last R/W status from J15 */ - if (sl->version.jtag_v >= 15) + + // preferred API to get last R/W status from J15 + if (sl->version.jtag_v >= 15) { sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2; + } } } else { // V3 uses different version format, for reference see OpenOCD source @@ -1265,13 +1319,16 @@ void _parse_version(stlink_t *sl, stlink_version_t *slv) { /* preferred API to get last R/W status */ sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2; } + return; } int stlink_version(stlink_t *sl) { DLOG("*** looking up stlink version\n"); - if (sl->backend->version(sl)) - return -1; + + if (sl->backend->version(sl)) { + return(-1); + } _parse_version(sl, &sl->version); @@ -1280,21 +1337,25 @@ int stlink_version(stlink_t *sl) { DLOG("stlink version = 0x%x\n", sl->version.stlink_v); DLOG("jtag version = 0x%x\n", sl->version.jtag_v); DLOG("swim version = 0x%x\n", sl->version.swim_v); + if (sl->version.jtag_v == 0) { DLOG(" notice: the firmware doesn't support a jtag/swd interface\n"); } + if (sl->version.swim_v == 0) { DLOG(" notice: the firmware doesn't support a swim interface\n"); } - return 0; + return(0); } int stlink_target_voltage(stlink_t *sl) { int voltage = -1; DLOG("*** reading target voltage\n"); + if (sl->backend->target_voltage != NULL) { voltage = sl->backend->target_voltage(sl); + if (voltage != -1) { DLOG("target voltage = %ldmV\n", voltage); } else { @@ -1303,66 +1364,76 @@ int stlink_target_voltage(stlink_t *sl) { } else { DLOG("reading voltage not supported by backend\n"); } - return voltage; + + return(voltage); } int stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { int ret; ret = sl->backend->read_debug32(sl, addr, data); - if (!ret) + + if (!ret) { DLOG("*** stlink_read_debug32 %x is %#x\n", *data, addr); + } - return ret; + return(ret); } int stlink_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { DLOG("*** stlink_write_debug32 %x to %#x\n", data, addr); - return sl->backend->write_debug32(sl, addr, data); + return(sl->backend->write_debug32(sl, addr, data)); } int stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { DLOG("*** stlink_write_mem32 %u bytes to %#x\n", len, addr); + if (len % 4 != 0) { - fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4); + fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", + len % 4); abort(); } - return sl->backend->write_mem32(sl, addr, len); + + return(sl->backend->write_mem32(sl, addr, len)); } int stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { DLOG("*** stlink_read_mem32 ***\n"); + if (len % 4 != 0) { // !!! never ever: fw gives just wrong values fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4); abort(); } - return sl->backend->read_mem32(sl, addr, len); + + return(sl->backend->read_mem32(sl, addr, len)); } int stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { DLOG("*** stlink_write_mem8 ***\n"); - if (len > 0x40){ // !!! never ever: Writing more then 0x40 bytes gives unexpected behaviour + + if (len > 0x40) { // !!! never ever: Writing more then 0x40 bytes gives unexpected behaviour fprintf(stderr, "Error: Data length > 64: +%d byte.\n", len); abort(); } - return sl->backend->write_mem8(sl, addr, len); + + return(sl->backend->write_mem8(sl, addr, len)); } int stlink_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { DLOG("*** stlink_read_all_regs ***\n"); - return sl->backend->read_all_regs(sl, regp); + return(sl->backend->read_all_regs(sl, regp)); } int stlink_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp) { DLOG("*** stlink_read_all_unsupported_regs ***\n"); - return sl->backend->read_all_unsupported_regs(sl, regp); + return(sl->backend->read_all_unsupported_regs(sl, regp)); } int stlink_write_reg(stlink_t *sl, uint32_t reg, int idx) { DLOG("*** stlink_write_reg\n"); - return sl->backend->write_reg(sl, reg, idx); + return(sl->backend->write_reg(sl, reg, idx)); } int stlink_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { @@ -1371,10 +1442,10 @@ int stlink_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { if (r_idx > 20 || r_idx < 0) { fprintf(stderr, "Error: register index must be in [0..20]\n"); - return -1; + return(-1); } - return sl->backend->read_reg(sl, r_idx, regp); + return(sl->backend->read_reg(sl, r_idx, regp)); } int stlink_read_unsupported_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { @@ -1384,18 +1455,18 @@ int stlink_read_unsupported_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp DLOG(" (%d) ***\n", r_idx); /* Convert to values used by STLINK_REG_DCRSR */ - if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */ + if (r_idx >= 0x1C && r_idx <= 0x1F) { // primask, basepri, faultmask, or control r_convert = 0x14; - } else if (r_idx == 0x40) { /* FPSCR */ + } else if (r_idx == 0x40) { // FPSCR r_convert = 0x21; } else if (r_idx >= 0x20 && r_idx < 0x40) { r_convert = 0x40 + (r_idx - 0x20); } else { fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n"); - return -1; + return(-1); } - return sl->backend->read_unsupported_reg(sl, r_convert, regp); + return(sl->backend->read_unsupported_reg(sl, r_convert, regp)); } int stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, struct stlink_reg *regp) { @@ -1406,45 +1477,46 @@ int stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, struct s /* Convert to values used by STLINK_REG_DCRSR */ if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */ - r_convert = r_idx; /* The backend function handles this */ - } else if (r_idx == 0x40) { /* FPSCR */ + r_convert = r_idx; // the backend function handles this + } else if (r_idx == 0x40) { // FPSCR r_convert = 0x21; } else if (r_idx >= 0x20 && r_idx < 0x40) { r_convert = 0x40 + (r_idx - 0x20); } else { fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n"); - return -1; + return(-1); } - return sl->backend->write_unsupported_reg(sl, val, r_convert, regp); + return(sl->backend->write_unsupported_reg(sl, val, r_convert, regp)); } -bool stlink_is_core_halted(stlink_t *sl) -{ +bool stlink_is_core_halted(stlink_t *sl) { stlink_status(sl); - return sl->core_stat == TARGET_HALTED; + return(sl->core_stat == TARGET_HALTED); } int stlink_step(stlink_t *sl) { DLOG("*** stlink_step ***\n"); - return sl->backend->step(sl); + return(sl->backend->step(sl)); } int stlink_current_mode(stlink_t *sl) { int mode = sl->backend->current_mode(sl); + switch (mode) { case STLINK_DEV_DFU_MODE: DLOG("stlink current mode: dfu\n"); - return mode; + return(mode); case STLINK_DEV_DEBUG_MODE: DLOG("stlink current mode: debug (jtag or swd)\n"); - return mode; + return(mode); case STLINK_DEV_MASS_MODE: DLOG("stlink current mode: mass\n"); - return mode; + return(mode); } + DLOG("stlink mode: unknown!\n"); - return STLINK_DEV_UNKNOWN_MODE; + return(STLINK_DEV_UNKNOWN_MODE); } @@ -1457,12 +1529,12 @@ int stlink_current_mode(stlink_t *sl) { unsigned int is_bigendian(void) { static volatile const unsigned int i = 1; - return *(volatile const char*) &i == 0; + return(*(volatile const char*)&i == 0); } uint16_t read_uint16(const unsigned char *c, const int pt) { uint32_t ui; - char *p = (char *) &ui; + char *p = (char *)&ui; if (!is_bigendian()) { // le -> le (don't swap) p[0] = c[pt + 0]; @@ -1471,18 +1543,17 @@ uint16_t read_uint16(const unsigned char *c, const int pt) { p[0] = c[pt + 1]; p[1] = c[pt + 0]; } - return ui; + + return(ui); } // same as above with entrypoint. void stlink_run_at(stlink_t *sl, stm32_addr_t addr) { stlink_write_reg(sl, addr, 15); /* pc register */ - stlink_run(sl); - while (stlink_is_core_halted(sl)) - usleep(3000000); + while (stlink_is_core_halted(sl)) { usleep(3000000); } } @@ -1508,27 +1579,26 @@ void stlink_core_stat(stlink_t *sl) { } void stlink_print_data(stlink_t * sl) { - if (sl->q_len <= 0 || sl->verbose < UDEBUG) - return; - if (sl->verbose > 2) - DLOG("data_len = %d 0x%x\n", sl->q_len, sl->q_len); + if (sl->q_len <= 0 || sl->verbose < UDEBUG) { return; } + + if (sl->verbose > 2) { DLOG("data_len = %d 0x%x\n", sl->q_len, sl->q_len); } for (int i = 0; i < sl->q_len; i++) { if (i % 16 == 0) { - /* - if (sl->q_data_dir == Q_DATA_OUT) - fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i); - else - fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i); - */ + // if (sl->q_data_dir == Q_DATA_OUT) { + // fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i); + // } else { + // fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i); + // } } - DLOG(" %02x", (unsigned int) sl->q_buf[i]); + + DLOG(" %02x", (unsigned int)sl->q_buf[i]); } + DLOG("\n\n"); } -/* memory mapped file */ - +/* Memory mapped file */ typedef struct mapped_file { uint8_t* base; size_t len; @@ -1541,86 +1611,85 @@ static int map_file(mapped_file_t* mf, const char* path) { struct stat st; const int fd = open(path, O_RDONLY | O_BINARY); + if (fd == -1) { fprintf(stderr, "open(%s) == -1\n", path); - return -1; + return(-1); } if (fstat(fd, &st) == -1) { fprintf(stderr, "fstat(%s) == -1\n", path); goto on_error; } + if (sizeof(st.st_size) != sizeof(size_t)) { - /* On 32 bit systems, check if there is an overflow */ + // on 32 bit systems, check if there is an overflow if (st.st_size > (off_t)UINT32_MAX) { fprintf(stderr, "mmap() size_t overflow for file %s\n", path); goto on_error; } } - mf->base = (uint8_t*) mmap(NULL, (size_t)(st.st_size), PROT_READ, MAP_SHARED, fd, 0); + + mf->base = (uint8_t*)mmap(NULL, (size_t)(st.st_size), PROT_READ, MAP_SHARED, fd, 0); + if (mf->base == MAP_FAILED) { fprintf(stderr, "mmap() == MAP_FAILED for file %s\n", path); goto on_error; } mf->len = st.st_size; - - /* success */ - error = 0; + error = 0; // success on_error: close(fd); - - return error; + return(error); } static void unmap_file(mapped_file_t * mf) { - munmap((void*) mf->base, mf->len); - mf->base = (unsigned char*) MAP_FAILED; + munmap((void*)mf->base, mf->len); + mf->base = (unsigned char*)MAP_FAILED; mf->len = 0; } -/* Limit the block size to compare to 0x1800 - Anything larger will stall the STLINK2 - Maybe STLINK V1 needs smaller value!*/ +/* Limit the block size to compare to 0x1800 as anything larger will stall the STLINK2 + * Maybe STLINK V1 needs smaller value! + */ static int check_file(stlink_t* sl, mapped_file_t* mf, stm32_addr_t addr) { size_t off; size_t n_cmp = sl->flash_pgsz; - if ( n_cmp > 0x1800) - n_cmp = 0x1800; + + if ( n_cmp > 0x1800) { n_cmp = 0x1800; } for (off = 0; off < mf->len; off += n_cmp) { size_t aligned_size; - /* adjust last page size */ - size_t cmp_size = n_cmp; - if ((off + n_cmp) > mf->len) - cmp_size = mf->len - off; + size_t cmp_size = n_cmp; // adjust last page size + + if ((off + n_cmp) > mf->len) { cmp_size = mf->len - off; } aligned_size = cmp_size; - if (aligned_size & (4 - 1)) - aligned_size = (cmp_size + 4) & ~(4 - 1); - stlink_read_mem32(sl, addr + (uint32_t) off, aligned_size); + if (aligned_size & (4 - 1)) { aligned_size = (cmp_size + 4) & ~(4 - 1); } + + stlink_read_mem32(sl, addr + (uint32_t)off, aligned_size); - if (memcmp(sl->q_buf, mf->base + off, cmp_size)) - return -1; + if (memcmp(sl->q_buf, mf->base + off, cmp_size)) { return(-1); } } - return 0; + return(0); } static void md5_calculate(mapped_file_t *mf) { - /* calculate md5 checksum of given binary file */ - Md5Context md5Context; - MD5_HASH md5Hash; + // calculate md5 checksum of given binary file + Md5Context md5Context; + MD5_HASH md5Hash; Md5Initialise(&md5Context); Md5Update(&md5Context, mf->base, (uint32_t)mf->len); Md5Finalise(&md5Context, &md5Hash); printf("md5 checksum: "); - for (int i = 0; i < (int) sizeof(md5Hash); i++) { - printf("%x", md5Hash.bytes[i]); - } + + for (int i = 0; i < (int)sizeof(md5Hash); i++) { printf("%x", md5Hash.bytes[i]); } + printf(", "); } @@ -1628,31 +1697,31 @@ static void stlink_checksum(mapped_file_t *mp) { /* checksum that backward compatible with official ST tools */ uint32_t sum = 0; uint8_t *mp_byte = (uint8_t *)mp->base; - for (size_t i = 0; i < mp->len; ++i) { - sum += mp_byte[i]; - } + + for (size_t i = 0; i < mp->len; ++i) { sum += mp_byte[i]; } + printf("stlink checksum: 0x%08x\n", sum); } static void stlink_fwrite_finalize(stlink_t *sl, stm32_addr_t addr) { unsigned int val; - /* set stack*/ + // set stack stlink_read_debug32(sl, addr, &val); stlink_write_reg(sl, val, 13); - /* Set PC to the reset routine*/ + // set PC to the reset routine stlink_read_debug32(sl, addr + 4, &val); stlink_write_reg(sl, val, 15); stlink_run(sl); } int stlink_mwrite_sram(stlink_t * sl, uint8_t* data, uint32_t length, stm32_addr_t addr) { - /* write the file in sram at addr */ + // write the file in sram at addr int error = -1; size_t off; size_t len; - /* check addr range is inside the sram */ + // check addr range is inside the sram if (addr < sl->sram_base) { fprintf(stderr, "addr too low\n"); goto on_error; @@ -1663,47 +1732,42 @@ int stlink_mwrite_sram(stlink_t * sl, uint8_t* data, uint32_t length, stm32_addr fprintf(stderr, "addr too high\n"); goto on_error; } else if (addr & 3) { - /* todo */ fprintf(stderr, "unaligned addr\n"); goto on_error; } len = length; - if (len & 3) { - len -= len & 3; - } + if (len & 3) { len -= len & 3; } - /* do the copy by 1k blocks */ + // do the copy by 1kB blocks for (off = 0; off < len; off += 1024) { size_t size = 1024; - if ((off + size) > len) - size = len - off; + + if ((off + size) > len) { size = len - off; } memcpy(sl->q_buf, data + off, size); - /* round size if needed */ - if (size & 3) - size += 2; + if (size & 3) { size += 2; } // round size if needed - stlink_write_mem32(sl, addr + (uint32_t) off, size); + stlink_write_mem32(sl, addr + (uint32_t)off, size); } if (length > len) { memcpy(sl->q_buf, data + len, length - len); - stlink_write_mem8(sl, addr + (uint32_t) len, length - len); + stlink_write_mem8(sl, addr + (uint32_t)len, length - len); } - /* success */ - error = 0; + + error = 0; // success stlink_fwrite_finalize(sl, addr); on_error: - return error; + return(error); } int stlink_fwrite_sram(stlink_t * sl, const char* path, stm32_addr_t addr) { - /* write the file in sram at addr */ + // write the file in sram at addr int error = -1; size_t off; @@ -1712,13 +1776,14 @@ int stlink_fwrite_sram(stlink_t * sl, const char* path, stm32_addr_t addr) { if (map_file(&mf, path) == -1) { fprintf(stderr, "map_file() == -1\n"); - return -1; + return(-1); } + printf("file %s ", path); md5_calculate(&mf); stlink_checksum(&mf); - /* check addr range is inside the sram */ + // check if addr range is inside the SRAM if (addr < sl->sram_base) { fprintf(stderr, "addr too low\n"); goto on_error; @@ -1729,88 +1794,80 @@ int stlink_fwrite_sram(stlink_t * sl, const char* path, stm32_addr_t addr) { fprintf(stderr, "addr too high\n"); goto on_error; } else if (addr & 3) { - /* todo */ fprintf(stderr, "unaligned addr\n"); goto on_error; } len = mf.len; - if (len & 3) { - len -= len & 3; - } + if (len & 3) { len -= len & 3; } - /* do the copy by 1k blocks */ + // do the copy by 1kB blocks for (off = 0; off < len; off += 1024) { size_t size = 1024; - if ((off + size) > len) - size = len - off; + + if ((off + size) > len) { size = len - off; } memcpy(sl->q_buf, mf.base + off, size); - /* round size if needed */ - if (size & 3) - size += 2; + if (size & 3) { size += 2; } // round size if needed - stlink_write_mem32(sl, addr + (uint32_t) off, size); + stlink_write_mem32(sl, addr + (uint32_t)off, size); } if (mf.len > len) { memcpy(sl->q_buf, mf.base + len, mf.len - len); - stlink_write_mem8(sl, addr + (uint32_t) len, mf.len - len); + stlink_write_mem8(sl, addr + (uint32_t)len, mf.len - len); } - /* check the file ha been written */ + // check the file has been written if (check_file(sl, &mf, addr) == -1) { fprintf(stderr, "check_file() == -1\n"); goto on_error; } - /* success */ - error = 0; + error = 0; // success stlink_fwrite_finalize(sl, addr); on_error: unmap_file(&mf); - return error; + return(error); } typedef bool (*save_block_fn)(void* arg, uint8_t* block, ssize_t len); -static int stlink_read(stlink_t* sl, stm32_addr_t addr, size_t size, save_block_fn fn, void* fn_arg) { +static int stlink_read( + stlink_t* sl, stm32_addr_t addr, size_t size, save_block_fn fn, void* fn_arg) { int error = -1; - if (size <1) - size = sl->flash_size; + if (size < 1) { size = sl->flash_size; } - if (size > sl->flash_size) + if (size > sl->flash_size) { size = sl->flash_size; + } + + size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz; - size_t cmp_size = (sl->flash_pgsz > 0x1800)? 0x1800:sl->flash_pgsz; for (size_t off = 0; off < size; off += cmp_size) { size_t aligned_size; - /* adjust last page size */ - if ((off + cmp_size) > size) - cmp_size = size - off; + // adjust last page size + if ((off + cmp_size) > size) { cmp_size = size - off; } aligned_size = cmp_size; - if (aligned_size & (4 - 1)) - aligned_size = (cmp_size + 4) & ~(4 - 1); - stlink_read_mem32(sl, addr + (uint32_t) off, aligned_size); + if (aligned_size & (4 - 1)) { aligned_size = (cmp_size + 4) & ~(4 - 1); } - if (!fn(fn_arg, sl->q_buf, aligned_size)) { - goto on_error; - } + stlink_read_mem32(sl, addr + (uint32_t)off, aligned_size); + + if (!fn(fn_arg, sl->q_buf, aligned_size)) { goto on_error; } } - /* success */ - error = 0; + error = 0; // success on_error: - return error; + return(error); } struct stlink_fread_worker_arg { @@ -1819,12 +1876,12 @@ struct stlink_fread_worker_arg { static bool stlink_fread_worker(void* arg, uint8_t* block, ssize_t len) { struct stlink_fread_worker_arg* the_arg = (struct stlink_fread_worker_arg*)arg; + if (write(the_arg->fd, block, len) != len) { fprintf(stderr, "write() != aligned_size\n"); - return false; - } - else { - return true; + return(false); + } else { + return(true); } } @@ -1839,45 +1896,56 @@ struct stlink_fread_ihex_worker_arg { static bool stlink_fread_ihex_newsegment(struct stlink_fread_ihex_worker_arg* the_arg) { uint32_t addr = the_arg->addr; uint8_t sum = 2 + 4 + (uint8_t)((addr & 0xFF000000) >> 24) + (uint8_t)((addr & 0x00FF0000) >> 16); - if (17 != fprintf(the_arg->file, ":02000004%04X%02X\r\n", (addr & 0xFFFF0000) >> 16, (uint8_t)(0x100 - sum))) - return false; - the_arg->lba = (addr & 0xFFFF0000); + if (17 != fprintf(the_arg->file, ":02000004%04X%02X\r\n", (addr & 0xFFFF0000) >> 16, + (uint8_t)(0x100 - sum))) { + return(false); + } - return true; + the_arg->lba = (addr & 0xFFFF0000); + return(true); } static bool stlink_fread_ihex_writeline(struct stlink_fread_ihex_worker_arg* the_arg) { uint8_t count = the_arg->buf_pos; - if (count == 0) return true; + + if (count == 0) { return(true); } uint32_t addr = the_arg->addr; if (the_arg->lba != (addr & 0xFFFF0000)) { // segment changed - if (!stlink_fread_ihex_newsegment(the_arg)) return false; + if (!stlink_fread_ihex_newsegment(the_arg)) { + return(false); + } } uint8_t sum = count + (uint8_t)((addr & 0x0000FF00) >> 8) + (uint8_t)(addr & 0x000000FF); - if (9 != fprintf(the_arg->file, ":%02X%04X00", count, (addr & 0x0000FFFF))) - return false; + + if (9 != fprintf(the_arg->file, ":%02X%04X00", count, (addr & 0x0000FFFF))) { + return(false); + } for (uint8_t i = 0; i < count; ++i) { uint8_t b = the_arg->buf[i]; sum += b; - if (2 != fprintf(the_arg->file, "%02X", b)) - return false; + + if (2 != fprintf(the_arg->file, "%02X", b)) { + return(false); + } } - if (4 != fprintf(the_arg->file, "%02X\r\n", (uint8_t)(0x100 - sum))) - return false; + if (4 != fprintf(the_arg->file, "%02X\r\n", (uint8_t)(0x100 - sum))) { + return(false); + } the_arg->addr += count; the_arg->buf_pos = 0; - return true; + return(true); } -static bool stlink_fread_ihex_init(struct stlink_fread_ihex_worker_arg* the_arg, int fd, stm32_addr_t addr) { +static bool stlink_fread_ihex_init( + struct stlink_fread_ihex_worker_arg* the_arg, int fd, stm32_addr_t addr) { the_arg->file = fdopen(fd, "w"); the_arg->addr = addr; the_arg->lba = 0; @@ -1891,109 +1959,127 @@ static bool stlink_fread_ihex_worker(void* arg, uint8_t* block, ssize_t len) { for (ssize_t i = 0; i < len; ++i) { if (the_arg->buf_pos == sizeof(the_arg->buf)) { // line is full - if (!stlink_fread_ihex_writeline(the_arg)) return false; + if (!stlink_fread_ihex_writeline(the_arg)) { return(false); } } the_arg->buf[the_arg->buf_pos++] = block[i]; } - return true; + return(true); } static bool stlink_fread_ihex_finalize(struct stlink_fread_ihex_worker_arg* the_arg) { - if (!stlink_fread_ihex_writeline(the_arg)) return false; + if (!stlink_fread_ihex_writeline(the_arg)) { return(false); } - // FIXME do we need the Start Linear Address? + // FIXME: do we need the Start Linear Address? - if (13 != fprintf(the_arg->file, ":00000001FF\r\n")) // EoF - return false; + if (13 != fprintf(the_arg->file, ":00000001FF\r\n")) { // EoF + return(false); + } return (0 == fclose(the_arg->file)); } int stlink_fread(stlink_t* sl, const char* path, bool is_ihex, stm32_addr_t addr, size_t size) { - /* read size bytes from addr to file */ + // read size bytes from addr to file int error; - int fd = open(path, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 00700); + if (fd == -1) { fprintf(stderr, "open(%s) == -1\n", path); - return -1; + return(-1); } if (is_ihex) { struct stlink_fread_ihex_worker_arg arg; + if (stlink_fread_ihex_init(&arg, fd, addr)) { error = stlink_read(sl, addr, size, &stlink_fread_ihex_worker, &arg); - if (!stlink_fread_ihex_finalize(&arg)) - error = -1; - } - else { + + if (!stlink_fread_ihex_finalize(&arg)) { error = -1; } + } else { error = -1; } - } - else { + } else { struct stlink_fread_worker_arg arg = { fd }; error = stlink_read(sl, addr, size, &stlink_fread_worker, &arg); } close(fd); - - return error; + return(error); } int write_buffer_to_sram(stlink_t *sl, flash_loader_t* fl, const uint8_t* buf, size_t size) { - /* write the buffer right after the loader */ + // write the buffer right after the loader size_t chunk = size & ~0x3; size_t rem = size & 0x3; + if (chunk) { memcpy(sl->q_buf, buf, chunk); stlink_write_mem32(sl, fl->buf_addr, chunk); } + if (rem) { - memcpy(sl->q_buf, buf+chunk, rem); - stlink_write_mem8(sl, (fl->buf_addr) + (uint32_t) chunk, rem); + memcpy(sl->q_buf, buf + chunk, rem); + stlink_write_mem8(sl, (fl->buf_addr) + (uint32_t)chunk, rem); } - return 0; + + return(0); } -uint32_t calculate_F4_sectornum(uint32_t flashaddr){ +uint32_t calculate_F4_sectornum(uint32_t flashaddr) { uint32_t offset = 0; - flashaddr &= ~STM32_FLASH_BASE; //Page now holding the actual flash address + flashaddr &= ~STM32_FLASH_BASE; // page now holding the actual flash address + if (flashaddr >= 0x100000) { offset = 12; flashaddr -= 0x100000; } - if (flashaddr<0x4000) return (offset + 0); - else if (flashaddr<0x8000) return(offset + 1); - else if (flashaddr<0xc000) return(offset + 2); - else if (flashaddr<0x10000) return(offset + 3); - else if (flashaddr<0x20000) return(offset + 4); - else return offset + (flashaddr/0x20000) +4; + + if (flashaddr < 0x4000) { + return (offset + 0); + } else if (flashaddr < 0x8000) { + return(offset + 1); + } else if (flashaddr < 0xc000) { + return(offset + 2); + } else if (flashaddr < 0x10000) { + return(offset + 3); + } else if (flashaddr < 0x20000) { + return(offset + 4); + } else { + return(offset + (flashaddr / 0x20000) + 4); + } } -uint32_t calculate_F7_sectornum(uint32_t flashaddr){ - flashaddr &= ~STM32_FLASH_BASE; //Page now holding the actual flash address - if (flashaddr<0x20000) return(flashaddr/0x8000); - else if (flashaddr<0x40000) return(4); - else return(flashaddr/0x40000) +4; +uint32_t calculate_F7_sectornum(uint32_t flashaddr) { + flashaddr &= ~STM32_FLASH_BASE; // Page now holding the actual flash address + + if (flashaddr < 0x20000) { + return(flashaddr / 0x8000); + } else if (flashaddr < 0x40000) { + return(4); + } else { + return((flashaddr / 0x40000) + 4); + } } -// Returns BKER:PNB for the given page address +// returns BKER:PNB for the given page address uint32_t calculate_L4_page(stlink_t *sl, uint32_t flashaddr) { uint32_t bker = 0; uint32_t flashopt; stlink_read_debug32(sl, STM32L4_FLASH_OPTR, &flashopt); flashaddr -= STM32_FLASH_BASE; + if (sl->chip_id == STLINK_CHIPID_STM32_L4 || sl->chip_id == STLINK_CHIPID_STM32_L496X || sl->chip_id == STLINK_CHIPID_STM32_L4RX) { - // This chip use dual banked flash + // this chip use dual banked flash if (flashopt & (uint32_t)(1lu << STM32L4_FLASH_OPTR_DUALBANK)) { - uint32_t banksize = (uint32_t) sl->flash_size / 2; + uint32_t banksize = (uint32_t)sl->flash_size / 2; + if (flashaddr >= banksize) { flashaddr -= banksize; bker = 0x100; @@ -2001,38 +2087,47 @@ uint32_t calculate_L4_page(stlink_t *sl, uint32_t flashaddr) { } } - // For 1MB chips without the dual-bank option set, the page address will - // overflow into the BKER bit, which gives us the correct bank:page value. - return bker | flashaddr/(uint32_t)sl->flash_pgsz; + // For 1MB chips without the dual-bank option set, the page address will overflow + // into the BKER bit, which gives us the correct bank:page value. + return(bker | flashaddr / (uint32_t)sl->flash_pgsz); } -uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){ +uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr) { if ((sl->chip_id == STLINK_CHIPID_STM32_F2) || (sl->chip_id == STLINK_CHIPID_STM32_F4) || (sl->chip_id == STLINK_CHIPID_STM32_F4_DE) || - (sl->chip_id == STLINK_CHIPID_STM32_F4_LP) || - (sl->chip_id == STLINK_CHIPID_STM32_F4_HD) || - (sl->chip_id == STLINK_CHIPID_STM32_F411RE) || - (sl->chip_id == STLINK_CHIPID_STM32_F446) || - (sl->chip_id == STLINK_CHIPID_STM32_F4_DSI) || - (sl->chip_id == STLINK_CHIPID_STM32_F72XXX) || - (sl->chip_id == STLINK_CHIPID_STM32_F412)) { - uint32_t sector=calculate_F4_sectornum(flashaddr); - if (sector>= 12) { - sector -= 12; + (sl->chip_id == STLINK_CHIPID_STM32_F4_LP) || + (sl->chip_id == STLINK_CHIPID_STM32_F4_HD) || + (sl->chip_id == STLINK_CHIPID_STM32_F411RE) || + (sl->chip_id == STLINK_CHIPID_STM32_F446) || + (sl->chip_id == STLINK_CHIPID_STM32_F4_DSI) || + (sl->chip_id == STLINK_CHIPID_STM32_F72XXX) || + (sl->chip_id == STLINK_CHIPID_STM32_F412)) { + uint32_t sector = calculate_F4_sectornum(flashaddr); + + if (sector >= 12) { sector -= 12; } + + if (sector < 4) { + sl->flash_pgsz = 0x4000; + } else if (sector < 5) { + sl->flash_pgsz = 0x10000; + } else { + sl->flash_pgsz = 0x20000; + } + } else if (sl->chip_id == STLINK_CHIPID_STM32_F7 || + sl->chip_id == STLINK_CHIPID_STM32_F7XXXX) { + uint32_t sector = calculate_F7_sectornum(flashaddr); + + if (sector < 4) { + sl->flash_pgsz = 0x8000; + } else if (sector < 5) { + sl->flash_pgsz = 0x20000; + } else { + sl->flash_pgsz = 0x40000; } - if (sector<4) sl->flash_pgsz=0x4000; - else if (sector<5) sl->flash_pgsz=0x10000; - else sl->flash_pgsz=0x20000; - } - else if (sl->chip_id == STLINK_CHIPID_STM32_F7 || - sl->chip_id == STLINK_CHIPID_STM32_F7XXXX) { - uint32_t sector=calculate_F7_sectornum(flashaddr); - if (sector<4) sl->flash_pgsz=0x8000; - else if (sector<5) sl->flash_pgsz=0x20000; - else sl->flash_pgsz=0x40000; } - return (uint32_t) sl->flash_pgsz; + + return((uint32_t)sl->flash_pgsz); } /** @@ -2041,17 +2136,16 @@ uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){ * @param flashaddr an address in the flash page to erase * @return 0 on success -ve on failure */ -int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) -{ +int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) { if (sl->flash_type == STLINK_FLASH_TYPE_F4 || sl->flash_type == STLINK_FLASH_TYPE_L4) { - /* wait for ongoing op to finish */ + // wait for ongoing op to finish wait_flash_busy(sl); - /* unlock if locked */ + // unlock if locked unlock_flash_if(sl); - /* select the page to erase */ + // select the page to erase if ((sl->chip_id == STLINK_CHIPID_STM32_L4) || (sl->chip_id == STLINK_CHIPID_STM32_L43X) || (sl->chip_id == STLINK_CHIPID_STM32_L46X) || @@ -2060,38 +2154,35 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) // calculate the actual bank+page from the address uint32_t page = calculate_L4_page(sl, flashaddr); - fprintf(stderr, "EraseFlash - Page:0x%x Size:0x%x ", page, stlink_calculate_pagesize(sl, flashaddr)); + fprintf(stderr, "EraseFlash - Page:0x%x Size:0x%x ", + page, stlink_calculate_pagesize(sl, flashaddr)); write_flash_cr_bker_pnb(sl, page); } else if (sl->chip_id == STLINK_CHIPID_STM32_F7 || sl->chip_id == STLINK_CHIPID_STM32_F7XXXX) { // calculate the actual page from the address - uint32_t sector=calculate_F7_sectornum(flashaddr); - - fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", sector, stlink_calculate_pagesize(sl, flashaddr)); + uint32_t sector = calculate_F7_sectornum(flashaddr); + fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", + sector, stlink_calculate_pagesize(sl, flashaddr)); write_flash_cr_snb(sl, sector); } else { // calculate the actual page from the address - uint32_t sector=calculate_F4_sectornum(flashaddr); + uint32_t sector = calculate_F4_sectornum(flashaddr); - fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", sector, stlink_calculate_pagesize(sl, flashaddr)); + fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x ", + sector, stlink_calculate_pagesize(sl, flashaddr)); - //the SNB values for flash sectors in the second bank do not directly follow the values for the first bank on 2mb devices... - if (sector >= 12) sector += 4; + // the SNB values for flash sectors in the second bank do not directly + // follow the values for the first bank on 2mb devices... + if (sector >= 12) { sector += 4; } write_flash_cr_snb(sl, sector); } - /* start erase operation */ - set_flash_cr_strt(sl); - - /* wait for completion */ - wait_flash_busy(sl); - - /* relock the flash */ - //todo: fails to program if this is in - lock_flash(sl); + set_flash_cr_strt(sl); // start erase operation + wait_flash_busy(sl); // wait for completion + lock_flash(sl); // TODO: fails to program if this is in #if DEBUG_FLASH fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl)); #endif @@ -2099,6 +2190,7 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) uint32_t val; uint32_t flash_regs_base; + if (sl->chip_id == STLINK_CHIPID_STM32_L0 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2 || @@ -2108,61 +2200,61 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) flash_regs_base = STM32L_FLASH_REGS_ADDR; } - /* check if the locks are set */ + // check if the locks are set stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - if ((val & (1<<0))||(val & (1<<1))) { - /* disable pecr protection */ + + if ((val & (1 << 0)) || (val & (1 << 1))) { + // disable pecr protection stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY1); stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY2); - /* check pecr.pelock is cleared */ + // check pecr.pelock is cleared stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 0)) { WLOG("pecr.pelock not clear (%#x)\n", val); - return -1; + return(-1); } - /* unlock program memory */ + // unlock program memory stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY1); stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY2); - /* check pecr.prglock is cleared */ + // check pecr.prglock is cleared stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 1)) { WLOG("pecr.prglock not clear (%#x)\n", val); - return -1; + return(-1); } } - /* set pecr.{erase,prog} */ + // set pecr.{erase,prog} val |= (1 << 9) | (1 << 3); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); -#if 0 /* fix_to_be_confirmed */ - - /* wait for sr.busy to be cleared - * MP: Test shows that busy bit is not set here. Perhaps, PM0062 is - * wrong and we do not need to wait here for clearing the busy bit. - * TEXANE: ok, if experience says so and it works for you, we comment - * it. If someone has a problem, please drop an email. +#if 0 + /* Wait for sr.busy to be cleared + * MP: Test shows that busy bit is not set here. Perhaps, PM0062 is wrong + * and we do not need to wait here for clearing the busy bit. */ do { stlink_read_debug32(sl, STM32L_FLASH_SR, &val) } while ((val & (1 << 0)) != 0); +#endif -#endif /* fix_to_be_confirmed */ - - /* write 0 to the first word of the page to be erased */ + // write 0 to the first word of the page to be erased stlink_write_debug32(sl, flashaddr, 0); - /* MP: It is better to wait for clearing the busy bit after issuing - page erase command, even though PM0062 recommends to wait before it. - Test shows that a few iterations is performed in the following loop - before busy bit is cleared.*/ - do { + /* MP: It is better to wait for clearing the busy bit after issuing page + * erase command, even though PM0062 recommends to wait before it. + * Test shows that a few iterations is performed in the following loop + * before busy bit is cleared. + */ + do stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); - } while ((val & (1 << 0)) != 0); + while ((val & (1 << 0)) != 0); - /* reset lock bits */ + // reset lock bits stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); val |= (1 << 0) | (1 << 1) | (1 << 2); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); @@ -2170,14 +2262,11 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_G4) { uint32_t val; - // Wait for any ongoing Flash operation to finish. - wait_flash_busy(sl); - // Unlock Flash if necessary. + wait_flash_busy(sl); // wait for any ongoing Flash operation to finish unlock_flash_if(sl); - // Set the 'enable Flash erase' bit. - set_flash_cr_per(sl); + set_flash_cr_per(sl); // set the 'enable Flash erase' bit - // Set the page to erase. + // set the page to erase if (sl->flash_type == STLINK_FLASH_TYPE_WB) { uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); stlink_read_debug32(sl, STM32WB_FLASH_CR, &val); @@ -2192,154 +2281,107 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); // sec 3.7.5 - PNB[5:0] is offset by 3. PER is 0x2. val &= ~(0x3F << 3); - val |= ((flash_page & 0x3F) << 3) | ( 1 << FLASH_CR_PER ); + val |= ((flash_page & 0x3F) << 3) | (1 << FLASH_CR_PER); stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); } else if (sl->flash_type == STLINK_FLASH_TYPE_G4) { uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); // sec 3.7.5 - PNB[6:0] is offset by 3. PER is 0x2. val &= ~(0x7F << 3); - val |= ((flash_page & 0x7F) << 3) | ( 1 << FLASH_CR_PER ); + val |= ((flash_page & 0x7F) << 3) | (1 << FLASH_CR_PER); stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); } - // Set the 'start operation' bit. - set_flash_cr_strt(sl); - // Wait for the 'busy' bit to clear. - wait_flash_busy(sl); - // Clear the 'enable page erase' bit. - clear_flash_cr_per(sl); - // Re-lock the flash. + set_flash_cr_strt(sl); // set the 'start operation' bit + wait_flash_busy(sl); // wait for the 'busy' bit to clear + clear_flash_cr_per(sl); // clear the 'enable page erase' bit lock_flash(sl); } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (flashaddr < FLASH_BANK2_START_ADDR))) { - /* wait for ongoing op to finish */ + ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (flashaddr < FLASH_BANK2_START_ADDR))) { wait_flash_busy(sl); - - /* unlock if locked */ unlock_flash_if(sl); - - /* clear the pg bit */ - clear_flash_cr_pg(sl); - - /* set the page erase bit */ - set_flash_cr_per(sl); - - /* select the page to erase */ - write_flash_ar(sl, flashaddr); - - /* start erase operation, reset by hw with bsy bit */ - set_flash_cr_strt(sl); - - /* wait for completion */ + clear_flash_cr_pg(sl); // clear the pg bit + set_flash_cr_per(sl); // set the page erase bit + write_flash_ar(sl, flashaddr); // select the page to erase + set_flash_cr_strt(sl); // start erase operation, reset by hw with busy bit wait_flash_busy(sl); - - /* relock the flash */ lock_flash(sl); } else if ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (flashaddr >= FLASH_BANK2_START_ADDR)) { - /* wait for ongoing op to finish */ wait_flash_busy(sl); - - /* unlock if locked */ unlock_flash_if(sl); - - /* set the page erase bit */ - set_flash_cr2_per(sl); - - /* select the page to erase */ - write_flash_ar2(sl, flashaddr); - - /* start erase operation, reset by hw with bsy bit */ - set_flash_cr2_strt(sl); - - /* wait for completion */ + set_flash_cr2_per(sl); // set the page erase bit + write_flash_ar2(sl, flashaddr); // select the page to erase + set_flash_cr2_strt(sl); // start erase operation, reset by hw with busy bit wait_flash_busy(sl); - - /* relock the flash */ lock_flash(sl); } else { WLOG("unknown coreid %x, page erase failed\n", sl->core_id); - return -1; + return(-1); } - /* todo: verify the erased page */ - - return 0; + // TODO: verify the erased page + return(0); } int stlink_erase_flash_mass(stlink_t *sl) { - /* TODO: User MER bit to mass-erase G0, G4, WB series. */ + // TODO: User MER bit to mass-erase G0, G4, WB series. if (sl->flash_type == STLINK_FLASH_TYPE_L0 || sl->flash_type == STLINK_FLASH_TYPE_WB) { - /* erase each page */ - int i = 0, num_pages = (int)(sl->flash_size/sl->flash_pgsz); + // erase each page + int i = 0, num_pages = (int)(sl->flash_size / sl->flash_pgsz); + for (i = 0; i < num_pages; i++) { - /* addr must be an addr inside the page */ - stm32_addr_t addr = (stm32_addr_t) sl->flash_base + i * (stm32_addr_t) sl->flash_pgsz; + // addr must be an addr inside the page + stm32_addr_t addr = (stm32_addr_t)sl->flash_base + i * (stm32_addr_t)sl->flash_pgsz; + if (stlink_erase_flash_page(sl, addr) == -1) { WLOG("Failed to erase_flash_page(%#zx) == -1\n", addr); - return -1; + return(-1); } - fprintf(stdout,"-> Flash page at %5d/%5d erased\n", i, num_pages); + + fprintf(stdout, "-> Flash page at %5d/%5d erased\n", i, num_pages); fflush(stdout); } + fprintf(stdout, "\n"); } else { - /* wait for ongoing op to finish */ wait_flash_busy(sl); - - /* unlock if locked */ unlock_flash_if(sl); - - /* set the mass erase bit */ - set_flash_cr_mer(sl,1); - - /* start erase operation, reset by hw with bsy bit */ - set_flash_cr_strt(sl); + set_flash_cr_mer(sl, 1); // set the mass erase bit + set_flash_cr_strt(sl); // start erase operation, reset by hw with busy bit if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { - /* set the mass erase bit in bank 2 */ - set_flash_cr2_mer(sl,1); - - /* start erase operation in bank 2 */ - set_flash_cr2_strt(sl); + set_flash_cr2_mer(sl, 1); // set the mass erase bit in bank 2 + set_flash_cr2_strt(sl); // start erase operation in bank 2 } - /* wait for completion */ wait_flash_busy_progress(sl); - check_flash_error(sl); - - /* relock the flash */ lock_flash(sl); - /* reset the mass erase bit */ - set_flash_cr_mer(sl,0); + set_flash_cr_mer(sl, 0); // reset the mass erase bit if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { - /* reset the mass erase bit in bank 2 */ - set_flash_cr2_mer(sl,0); + set_flash_cr2_mer(sl, 0); // reset the mass erase bit in bank 2 } - /* todo: verify the erased memory */ + // TODO: verify the erased memory } - return 0; + + return(0); } int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { - /* check the contents of path are at addr */ + // check the contents of path are at addr int res; mapped_file_t mf = MAPPED_FILE_INITIALIZER; - if (map_file(&mf, path) == -1) - return -1; + if (map_file(&mf, path) == -1) { return(-1); } res = check_file(sl, &mf, addr); - unmap_file(&mf); - - return res; + return(res); } /** @@ -2352,33 +2394,34 @@ int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { */ int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, unsigned length) { size_t off; - size_t cmp_size = (sl->flash_pgsz > 0x1800)? 0x1800:sl->flash_pgsz; + size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz; ILOG("Starting verification of write complete\n"); + for (off = 0; off < length; off += cmp_size) { size_t aligned_size; - /* adjust last page size */ - if ((off + cmp_size) > length) - cmp_size = length - off; + // adjust last page size + if ((off + cmp_size) > length) { cmp_size = length - off; } aligned_size = cmp_size; - if (aligned_size & (4 - 1)) - aligned_size = (cmp_size + 4) & ~(4 - 1); - stlink_read_mem32(sl, address + (uint32_t) off, aligned_size); + if (aligned_size & (4 - 1)) { aligned_size = (cmp_size + 4) & ~(4 - 1); } + + stlink_read_mem32(sl, address + (uint32_t)off, aligned_size); if (memcmp(sl->q_buf, data + off, cmp_size)) { ELOG("Verification of flash failed at offset: %u\n", (unsigned int)off); - return -1; + return(-1); } } + ILOG("Flash written and verified! jolly good!\n"); - return 0; + return(0); } -int stm32l1_write_half_pages(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len, uint32_t pagesize) -{ +int stm32l1_write_half_pages( + stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len, uint32_t pagesize) { unsigned int count; unsigned int num_half_pages = len / pagesize; uint32_t val; @@ -2395,215 +2438,223 @@ int stm32l1_write_half_pages(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uin } ILOG("Starting Half page flash write for STM32L core id\n"); - /* flash loader initialization */ + + /* Flash loader initialisation */ if (stlink_flash_loader_init(sl, &fl) == -1) { WLOG("stlink_flash_loader_init() == -1\n"); - return -1; + return(-1); } - /* Unlock already done */ + + // unlock already done stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); val |= (1 << FLASH_L1_FPRG); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); val |= (1 << FLASH_L1_PROG); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); + do { stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); } while ((val & (1 << 0)) != 0); - for (count = 0; count < num_half_pages; count ++) { - if (stlink_flash_loader_run(sl, &fl, addr + count * pagesize, base + count * pagesize, pagesize) == -1) { + for (count = 0; count < num_half_pages; count++) { + if (stlink_flash_loader_run( + sl, &fl, addr + count * pagesize, base + count * pagesize, pagesize) == -1) { WLOG("l1_stlink_flash_loader_run(%#zx) failed! == -1\n", addr + count * pagesize); stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); - val &= ~((1 << FLASH_L1_FPRG) |(1 << FLASH_L1_PROG)); + val &= ~((1 << FLASH_L1_FPRG) | (1 << FLASH_L1_PROG)); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - return -1; + return(-1); } - /* wait for sr.busy to be cleared */ + + // wait for sr.busy to be cleared if (sl->verbose >= 1) { - /* show progress. writing procedure is slow - and previous errors are misleading */ + // show progress; writing procedure is slow and previous errors are misleading fprintf(stdout, "\r%3u/%u halfpages written", count + 1, num_half_pages); fflush(stdout); } + do { stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); } while ((val & (1 << 0)) != 0); } + stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); val &= ~(1 << FLASH_L1_PROG); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); val &= ~(1 << FLASH_L1_FPRG); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - - return 0; + return(0); } -int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len, uint8_t eraseonly) { +int stlink_write_flash( + stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len, uint8_t eraseonly) { size_t off; flash_loader_t fl; - ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", - len, len, addr, addr); - /* check addr range is inside the flash */ + ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr); + // check addr range is inside the flash stlink_calculate_pagesize(sl, addr); + if (addr < sl->flash_base) { ELOG("addr too low %#x < %#x\n", addr, sl->flash_base); - return -1; + return(-1); } else if ((addr + len) < addr) { ELOG("addr overruns\n"); - return -1; + return(-1); } else if ((addr + len) > (sl->flash_base + sl->flash_size)) { ELOG("addr too high\n"); - return -1; + return(-1); } else if (addr & 1) { ELOG("unaligned addr 0x%x\n", addr); - return -1; + return(-1); } else if (len & 1) { WLOG("unaligned len 0x%x -- padding with zero\n", len); len += 1; } else if (addr & (sl->flash_pgsz - 1)) { - ELOG("addr not a multiple of current pagesize (%zd bytes), not supported, check page start address and compare with flash module organisation in related ST reference manual of your device.\n", sl->flash_pgsz); - return -1; + ELOG("addr not a multiple of current pagesize (%zd bytes), not supported, " + "check page start address and compare with flash module organisation " + "in related ST reference manual of your device.\n", sl->flash_pgsz); + return(-1); } - // Make sure we've loaded the context with the chip details + // make sure we've loaded the context with the chip details stlink_core_id(sl); - /* erase each page */ + + // Erase each page int page_count = 0; - for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + (uint32_t) off)) { + + for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + (uint32_t)off)) { // addr must be an addr inside the page - if (stlink_erase_flash_page(sl, addr + (uint32_t) off) == -1) { + if (stlink_erase_flash_page(sl, addr + (uint32_t)off) == -1) { ELOG("Failed to erase_flash_page(%#zx) == -1\n", addr + off); - return -1; + return(-1); } - ILOG("Flash page at addr: 0x%08lx erased\n", - (unsigned long)(addr + off)); + + ILOG("Flash page at addr: 0x%08lx erased\n", (unsigned long)(addr + off)); page_count++; } + ILOG("Finished erasing %d pages of %d (%#x) bytes\n", - page_count, sl->flash_pgsz, sl->flash_pgsz); + page_count, sl->flash_pgsz, sl->flash_pgsz); - if (eraseonly) - return 0; + if (eraseonly) { return(0); } if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || (sl->flash_type == STLINK_FLASH_TYPE_L4)) { - /* todo: check write operation */ + // TODO: check write operation ILOG("Starting Flash write for F2/F4/L4\n"); - /* flash loader initialization */ + + // Flash loader initialisation if (stlink_flash_loader_init(sl, &fl) == -1) { ELOG("stlink_flash_loader_init() == -1\n"); - return -1; + return(-1); } - /* First unlock the cr */ - unlock_flash_if(sl); + unlock_flash_if(sl); // first unlock the cr - /* TODO: Check that Voltage range is 2.7 - 3.6 V */ + // TODO: Check that Voltage range is 2.7 - 3.6 V if ((sl->chip_id != STLINK_CHIPID_STM32_L4) && (sl->chip_id != STLINK_CHIPID_STM32_L43X) && (sl->chip_id != STLINK_CHIPID_STM32_L46X) && (sl->chip_id != STLINK_CHIPID_STM32_L496X) && (sl->chip_id != STLINK_CHIPID_STM32_L4RX)) { - if ( sl->version.stlink_v == 1){ - printf("STLINK V1 cannot read voltage, defaulting to 32-bit writes on F4 devices\n"); + if ( sl->version.stlink_v == 1) { + printf("STLINK V1 cannot read voltage, defaulting to 32-bit " + "writes on F4 devices\n"); write_flash_cr_psiz(sl, 2); - } - else { - /* set parallelisim to 32 bit*/ + } else { + // set parallelism to 32 bit int voltage = stlink_target_voltage(sl); + if (voltage == -1) { printf("Failed to read Target voltage\n"); - return voltage; + return(voltage); } else if (voltage > 2700) { printf("enabling 32-bit flash writes\n"); write_flash_cr_psiz(sl, 2); } else { - printf("Target voltage (%d mV) too low for 32-bit flash, using 8-bit flash writes\n", voltage); + printf("Target voltage (%d mV) too low for 32-bit flash, " + "using 8-bit flash writes\n", voltage); write_flash_cr_psiz(sl, 0); } } } else { - /* L4 does not have a byte-write mode */ + // L4 does not have a byte-write mode int voltage = stlink_target_voltage(sl); + if (voltage == -1) { printf("Failed to read Target voltage\n"); - return voltage; + return(voltage); } else if (voltage < 1710) { printf("Target voltage (%d mV) too low for flash writes!\n", voltage); - return -1; + return(-1); } } - /* set programming mode */ + // set programming mode set_flash_cr_pg(sl); size_t buf_size = (sl->sram_size > 0x8000) ? 0x8000 : 0x4000; + for (off = 0; off < len;) { size_t size = len - off > buf_size ? buf_size : len - off; - printf("size: %u\n", (unsigned int)size); - if (stlink_flash_loader_run(sl, &fl, addr + (uint32_t) off, base + off, size) == -1) { + if (stlink_flash_loader_run(sl, &fl, addr + (uint32_t)off, base + off, size) == -1) { ELOG("stlink_flash_loader_run(%#zx) failed! == -1\n", addr + off); - return -1; + return(-1); } off += size; } - /* Relock flash */ clear_flash_cr_pg(sl); lock_flash(sl); - } //STM32F4END - else if (sl->flash_type == STLINK_FLASH_TYPE_WB || - sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4) { + // STM32F4END + } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || + sl->flash_type == STLINK_FLASH_TYPE_G0 || + sl->flash_type == STLINK_FLASH_TYPE_G4) { fprintf(stdout, "Writing\r\n"); fflush(stdout); - // Wait for any ongoing operations to finish. wait_flash_busy(sl); - // Unlock flash if necessary. - unlock_flash_if(sl); - // Set PG 'allow programming' bit. - set_flash_cr_pg(sl); - // Write all words. + unlock_flash_if(sl); // unlock flash if necessary + set_flash_cr_pg(sl); // set PG 'allow programming' bit + // write all words. off = 0; - fprintf(stdout, "Starting %3u page write\r\n", (unsigned int)(len/sl->flash_pgsz)); + fprintf(stdout, "Starting %3u page write\r\n", (unsigned int)(len / sl->flash_pgsz)); fflush(stdout); + for ( ; off < len; off += sizeof(uint32_t)) { uint32_t data; - if (off > 254) - fprintf(stdout, "\r"); - if ((off % sl->flash_pgsz) > (sl->flash_pgsz -5)) { + if (off > 254) { fprintf(stdout, "\r"); } + + if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) { fprintf(stdout, "\r%3u/%3u pages written", - (unsigned int)(off/sl->flash_pgsz), - (unsigned int)(len/sl->flash_pgsz)); + (unsigned int)(off / sl->flash_pgsz), + (unsigned int)(len / sl->flash_pgsz)); fflush(stdout); } - write_uint32((unsigned char*) &data, *(uint32_t*) (base + off)); - stlink_write_debug32(sl, addr + (uint32_t) off, data); - // Wait for 'busy' bit in FLASH_SR to clear. - wait_flash_busy(sl); + + write_uint32((unsigned char*)&data, *(uint32_t*)(base + off)); + stlink_write_debug32(sl, addr + (uint32_t)off, data); + wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear } - // (Flash writes happen 2 words at a time.) + + // flash writes happen as 2 words at a time if ((off / sizeof(uint32_t)) % 2 != 0) { - // Write a single word of zeros. - stlink_write_debug32(sl, addr + (uint32_t) off, 0); - // Wait for 'busy' bit in FLASH_SR to clear. - wait_flash_busy(sl); + stlink_write_debug32(sl, addr + (uint32_t)off, 0); // write a single word of zeros + wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear } - // Reset PG bit. - clear_flash_cr_pg(sl); - // Re-lock flash. + + clear_flash_cr_pg(sl); // reset PG bit. lock_flash(sl); - } - else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { - /* use fast word write. todo: half page. */ + } else if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + // use fast word write + // TODO: half page uint32_t val; uint32_t flash_regs_base; uint32_t pagesize; @@ -2619,130 +2670,152 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t pagesize = L1_WRITE_BLOCK_SIZE; } - /* todo: check write operation */ + // TODO: check write operation - /* disable pecr protection */ + // disable pecr protection stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY1); stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF, FLASH_L0_PEKEY2); - /* check pecr.pelock is cleared */ + // check pecr.pelock is cleared stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 0)) { fprintf(stderr, "pecr.pelock not clear\n"); - return -1; + return(-1); } - /* unlock program memory */ + // unlock program memory stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY1); stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF, FLASH_L0_PRGKEY2); - /* check pecr.prglock is cleared */ + // check pecr.prglock is cleared stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); + if (val & (1 << 1)) { fprintf(stderr, "pecr.prglock not clear\n"); - return -1; + return(-1); } + off = 0; + if (len > pagesize) { if (stm32l1_write_half_pages(sl, addr, base, len, pagesize) == -1) { - /* This may happen on a blank device! */ + // this may happen on a blank device! WLOG("\nwrite_half_pages failed == -1\n"); } else { - off = (len / pagesize)*pagesize; + off = (len / pagesize) * pagesize; } } - /* write remainingword in program memory */ + // write remaining word in program memory for ( ; off < len; off += sizeof(uint32_t)) { uint32_t data; - if (off > 254) - fprintf(stdout, "\r"); - if ((off % sl->flash_pgsz) > (sl->flash_pgsz -5)) { + if (off > 254) { fprintf(stdout, "\r"); } + + if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) { fprintf(stdout, "\r%3u/%3u pages written", - (unsigned int)(off/sl->flash_pgsz), - (unsigned int)(len/sl->flash_pgsz)); + (unsigned int)(off / sl->flash_pgsz), + (unsigned int)(len / sl->flash_pgsz)); fflush(stdout); } - write_uint32((unsigned char*) &data, *(uint32_t*) (base + off)); - stlink_write_debug32(sl, addr + (uint32_t) off, data); + write_uint32((unsigned char*)&data, *(uint32_t*)(base + off)); + stlink_write_debug32(sl, addr + (uint32_t)off, data); - /* wait for sr.busy to be cleared */ + // wait for sr.busy to be cleared do { stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val); } while ((val & (1 << 0)) != 0); - /* todo: check redo write operation */ - + // TODO: check redo write operation } + fprintf(stdout, "\n"); - /* reset lock bits */ + // reset lock bits stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); val |= (1 << 0) | (1 << 1) | (1 << 2); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); - } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { ILOG("Starting Flash write for VL/F0/F3/F1_XL core id\n"); - /* flash loader initialization */ + + // flash loader initialisation if (stlink_flash_loader_init(sl, &fl) == -1) { ELOG("stlink_flash_loader_init() == -1\n"); - return -1; + return(-1); } int write_block_count = 0; + for (off = 0; off < len; off += sl->flash_pgsz) { - /* adjust last write size */ + // adjust last write size size_t size = sl->flash_pgsz; - if ((off + sl->flash_pgsz) > len) size = len - off; - /* unlock and set programming mode */ + if ((off + sl->flash_pgsz) > len) { size = len - off; } + + // unlock and set programming mode unlock_flash_if(sl); - if (sl->flash_type != STLINK_FLASH_TYPE_F1_XL) { - set_flash_cr_pg(sl); - } + + if (sl->flash_type != STLINK_FLASH_TYPE_F1_XL) { set_flash_cr_pg(sl); } + DLOG("Finished unlocking flash, running loader!\n"); - if (stlink_flash_loader_run(sl, &fl, addr + (uint32_t) off, base + off, size) == -1) { + + if (stlink_flash_loader_run(sl, &fl, addr + (uint32_t)off, base + off, size) == -1) { ELOG("stlink_flash_loader_run(%#zx) failed! == -1\n", addr + off); - return -1; + return(-1); } + lock_flash(sl); + if (sl->verbose >= 1) { - /* show progress. writing procedure is slow - and previous errors are misleading */ - fprintf(stdout, "\r%3u/%lu pages written", ++write_block_count, (unsigned long)((len+sl->flash_pgsz-1)/sl->flash_pgsz)); + // show progress; writing procedure is slow and previous errors are misleading + fprintf(stdout, "\r%3u/%lu pages written", ++write_block_count, + (unsigned long)((len + sl->flash_pgsz - 1) / sl->flash_pgsz)); fflush(stdout); } } + fprintf(stdout, "\n"); } else { ELOG("unknown coreid, not sure how to write: %x\n", sl->core_id); - return -1; + return(-1); } - return stlink_verify_write_flash(sl, addr, base, len); + return(stlink_verify_write_flash(sl, addr, base, len)); } -// note: length not checked +// TODO: length not checked static uint8_t stlink_parse_hex(const char* hex) { uint8_t d[2]; + for (int i = 0; i < 2; ++i) { char c = *(hex + i); - if (c >= '0' && c <= '9') d[i] = c - '0'; - else if (c >= 'A' && c <= 'F') d[i] = c - 'A' + 10; - else if (c >= 'a' && c <= 'f') d[i] = c - 'a' + 10; - else return 0; // error + + if (c >= '0' && c <= '9') { + d[i] = c - '0'; + } else if (c >= 'A' && c <= 'F') { + d[i] = c - 'A' + 10; + } else if (c >= 'a' && c <= 'f') { + d[i] = c - 'a' + 10; + } else { + return(0); // error + } } - return (d[0] << 4) | (d[1]); + + return((d[0] << 4) | (d[1])); } -int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, size_t * size, uint32_t * begin) { +int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, size_t * size, + uint32_t * begin) { int res = 0; *begin = UINT32_MAX; uint8_t* data = NULL; uint32_t end = 0; bool eof_found = false; - for (int scan = 0; (res == 0) && (scan < 2); ++scan) { // parse file two times - first to find memory range, second - to fill it + for (int scan = 0; (res == 0) && (scan < 2); ++scan) { + // parse file two times - first to find memory range, second - to fill it if (scan == 1) { if (!eof_found) { ELOG("No EoF recond\n"); @@ -2758,6 +2831,7 @@ int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, *size = (end - *begin) + 1; data = calloc(*size, 1); // use calloc to get NULL if out of memory + if (!data) { ELOG("Cannot allocate %d bytes\n", *size); res = -1; @@ -2768,6 +2842,7 @@ int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, } FILE* file = fopen(path, "r"); + if (!file) { ELOG("Cannot open file\n"); res = -1; @@ -2775,10 +2850,11 @@ int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, } uint32_t lba = 0; + char line[1 + 5 * 2 + 255 * 2 + 2]; - char line[1 + 5*2 + 255*2 + 2]; while (fgets(line, sizeof(line), file)) { - if (line[0] == '\n' || line[0] == '\r') continue; // skip empty lines + if (line[0] == '\n' || line[0] == '\r') { continue; } // skip empty lines + if (line[0] != ':') { // no marker - wrong file format ELOG("Wrong file format - no marker\n"); res = -1; @@ -2786,18 +2862,19 @@ int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, } size_t l = strlen(line); - while (l > 0 && (line[l-1] == '\n' || line[l-1] == '\r')) --l; // trim EoL - if ((l < 11) || (l == (sizeof(line)-1))) { // line too short or long - wrong file format + + while (l > 0 && (line[l - 1] == '\n' || line[l - 1] == '\r')) { --l; } // trim EoL + + if ((l < 11) || (l == (sizeof(line) - 1))) { // line too short or long - wrong file format ELOG("Wrong file format - wrong line length\n"); res = -1; break; } - // check sum - uint8_t chksum = 0; - for (size_t i = 1; i < l; i += 2) { - chksum += stlink_parse_hex(line + i); - } + uint8_t chksum = 0; // check sum + + for (size_t i = 1; i < l; i += 2) { chksum += stlink_parse_hex(line + i); } + if (chksum != 0) { ELOG("Wrong file format - checksum mismatch\n"); res = -1; @@ -2805,64 +2882,61 @@ int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, } uint8_t reclen = stlink_parse_hex(line + 1); - if (((uint32_t)reclen + 5)*2 + 1 != l) { + + if (((uint32_t)reclen + 5) * 2 + 1 != l) { ELOG("Wrong file format - record length mismatch\n"); res = -1; break; } - uint16_t offset = ((uint16_t)stlink_parse_hex(line + 3) << 8) | ((uint16_t)stlink_parse_hex(line + 5)); - uint8_t rectype = stlink_parse_hex(line + 7); + uint16_t offset = ((uint16_t)stlink_parse_hex(line + 3) << 8) | + ((uint16_t)stlink_parse_hex(line + 5)); + uint8_t rectype = stlink_parse_hex(line + 7); - switch(rectype) { - case 0: // data - if (scan == 0) { - uint32_t b = lba + offset; - uint32_t e = b + reclen - 1; - if (b < *begin) *begin = b; - if (e > end) end = e; - } - else { - for (uint8_t i = 0; i < reclen; ++i) { - uint8_t b = stlink_parse_hex(line + 9 + i*2); - uint32_t addr = lba + offset + i; - if (addr >= *begin && addr <= end) { - data[addr - *begin] = b; - } - } - } - break; + switch (rectype) { + case 0: /* Data */ + if (scan == 0) { + uint32_t b = lba + offset; + uint32_t e = b + reclen - 1; - case 1: // EoF - eof_found = true; - break; + if (b < *begin) { *begin = b; } - case 2: // Extended Segment Address, unexpected - res = -1; - break; - - case 3: // Start Segment Address, unexpected - res = -1; - break; + if (e > end) { end = e; } + } else { + for (uint8_t i = 0; i < reclen; ++i) { + uint8_t b = stlink_parse_hex(line + 9 + i * 2); + uint32_t addr = lba + offset + i; - case 4: // Extended Linear Address - if (reclen == 2) { - lba = ((uint32_t)stlink_parse_hex(line + 9) << 24) | ((uint32_t)stlink_parse_hex(line + 11) << 16); + if (addr >= *begin && addr <= end) { data[addr - *begin] = b; } } - else { - ELOG("Wrong file format - wrong LBA length\n"); - res = -1; - } - break; - - case 5: // Start Linear Address - expected, but ignore - break; - - default: - ELOG("Wrong file format - unexpected record type %d\n", rectype); + } + break; + case 1: /* EoF */ + eof_found = true; + break; + case 2: /* Extended Segment Address, unexpected */ + res = -1; + break; + case 3: /* Start Segment Address, unexpected */ + res = -1; + break; + case 4: /* Extended Linear Address */ + if (reclen == 2) { + lba = ((uint32_t)stlink_parse_hex(line + 9) << 24) | + ((uint32_t)stlink_parse_hex(line + 11) << 16); + } else { + ELOG("Wrong file format - wrong LBA length\n"); res = -1; + } + break; + case 5: /* Start Linear Address - expected, but ignore */ + break; + default: + ELOG("Wrong file format - unexpected record type %d\n", rectype); + res = -1; } - if (res != 0) break; + + if (res != 0) { break; } } fclose(file); @@ -2870,55 +2944,56 @@ int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, if (res == 0) { *mem = data; - } - else { + } else { free(data); } - return res; + return(res); } uint8_t stlink_get_erased_pattern(stlink_t *sl) { - if (sl->flash_type == STLINK_FLASH_TYPE_L0) - return 0x00; - else - return 0xff; + if (sl->flash_type == STLINK_FLASH_TYPE_L0) { + return(0x00); + } else { + return(0xff); + } } int stlink_mwrite_flash(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr_t addr) { - /* write the block in flash at addr */ + /* Write the block in flash at addr */ int err; unsigned int num_empty, idx; uint8_t erased_pattern = stlink_get_erased_pattern(sl); /* - * This optimization may cause unexpected garbage data remaining - * Turned off by default + * This optimisation may cause unexpected garbage data remaining. + * Therfore it is turned off by default. */ if (sl->opt) { idx = (unsigned int)length; - for (num_empty = 0; num_empty != length; ++num_empty) { - if (data[--idx] != erased_pattern) { - break; - } - } - /* Round down to words */ - num_empty -= (num_empty & 3); + + for (num_empty = 0; num_empty != length; ++num_empty) + if (data[--idx] != erased_pattern) { break; } + + num_empty -= (num_empty & 3); // Round down to words + if (num_empty != 0) { ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, erased_pattern); } } else { num_empty = 0; } + /* - * TODO: investigate: - * a kind of weird behaviour here: - * if the file is identified to be all-empty and four-bytes aligned, - * still flash the whole file even if ignoring message is printed + * TODO: investigate a kind of weird behaviour here: + * If the file is identified to be all-empty and four-bytes aligned, + * still flash the whole file even if ignoring message is printed. */ - err = stlink_write_flash(sl, addr, data, (num_empty == length) ? (uint32_t) length : (uint32_t) length - num_empty, num_empty == length); + err = stlink_write_flash(sl, addr, data, + (num_empty == length) ? (uint32_t)length : (uint32_t)length - num_empty, + num_empty == length); stlink_fwrite_finalize(sl, addr); - return err; + return(err); } /** @@ -2929,7 +3004,7 @@ int stlink_mwrite_flash(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr * @return 0 on success, -ve on failure. */ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { - /* write the file in flash at addr */ + /* Write the file in flash at addr */ int err; unsigned int num_empty, idx; uint8_t erased_pattern = stlink_get_erased_pattern(sl); @@ -2937,7 +3012,7 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { if (map_file(&mf, path) == -1) { ELOG("map_file() == -1\n"); - return -1; + return(-1); } printf("file %s ", path); @@ -2945,30 +3020,32 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { stlink_checksum(&mf); if (sl->opt) { - idx = (unsigned int) mf.len; + idx = (unsigned int)mf.len; + for (num_empty = 0; num_empty != mf.len; ++num_empty) { - if (mf.base[--idx] != erased_pattern) { - break; - } + if (mf.base[--idx] != erased_pattern) { break; } } - /* Round down to words */ - num_empty -= (num_empty & 3); + + num_empty -= (num_empty & 3); // round down to words + if (num_empty != 0) { ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, erased_pattern); } } else { num_empty = 0; } + /* - * TODO: investigate: - * a kind of weird behaviour here: - * if the file is identified to be all-empty and four-bytes aligned, - * still flash the whole file even if ignoring message is printed + * TODO: investigate a kind of weird behaviour here: + * If the file is identified to be all-empty and four-bytes aligned, + * still flash the whole file even if ignoring message is printed. */ - err = stlink_write_flash(sl, addr, mf.base, (num_empty == mf.len) ? (uint32_t) mf.len : (uint32_t) mf.len - num_empty, num_empty == mf.len); + err = stlink_write_flash(sl, addr, mf.base, + (num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty, + num_empty == mf.len); stlink_fwrite_finalize(sl, addr); unmap_file(&mf); - return err; + return(err); } /** @@ -2978,20 +3055,19 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { * @param base option bytes to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_gx(stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { - +static int stlink_write_option_bytes_gx( + stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { + /* Write options bytes */ uint32_t val; int ret = 0; - (void) len; - - /* Write options bytes */ + (void)len; uint32_t data; - write_uint32((unsigned char*) &data, *(uint32_t*) (base)); - WLOG("Writing option bytes %#10x to %#10x\n", data, addr); + write_uint32((unsigned char*)&data, *(uint32_t*)(base)); + WLOG("Writing option bytes %#10x to %#10x\n", data, addr); stlink_write_debug32(sl, STM32Gx_FLASH_OPTR, data); - /* Set Options Start bit */ + // Set Options Start bit stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); val |= (1 << STM32Gx_FLASH_CR_OPTSTRT); stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); @@ -3000,12 +3076,12 @@ static int stlink_write_option_bytes_gx(stlink_t *sl, uint8_t* base, stm32_addr_ ret = check_flash_error(sl); - /* Reload options */ + // Reload options stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); val |= (1 << STM32Gx_FLASH_CR_OBL_LAUNCH); stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); - return ret; + return(ret); } /** @@ -3015,39 +3091,36 @@ static int stlink_write_option_bytes_gx(stlink_t *sl, uint8_t* base, stm32_addr_ * @param base option bytes to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_l0(stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) -{ +static int stlink_write_option_bytes_l0( + stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { uint32_t flash_base = get_stm32l0_flash_base(sl); uint32_t val; uint32_t data; int ret = 0; - /* Clear errors */ + // Clear errors stlink_write_debug32(sl, flash_base + FLASH_SR_OFF, STM32L0_FLASH_REGS_ADDR); while (len != 0) { - /* Write options bytes */ - write_uint32((unsigned char*) &data, *(uint32_t*) (base)); + write_uint32((unsigned char*)&data, *(uint32_t*)(base)); // write options bytes WLOG("Writing option bytes %#10x to %#10x\n", data, addr); stlink_write_debug32(sl, addr, data); - wait_flash_busy(sl); - if ((ret = check_flash_error(sl))) - break; + if ((ret = check_flash_error(sl))) { break; } - len-=4; - addr+=4; - base+=4; + len -= 4; + addr += 4; + base += 4; } - /* Reload options */ + // Reload options stlink_read_debug32(sl, flash_base + FLASH_PECR_OFF, &val); val |= (1 << STM32L0_FLASH_OBL_LAUNCH); stlink_write_debug32(sl, flash_base + FLASH_PECR_OFF, val); - return ret; + return(ret); } /** @@ -3057,36 +3130,34 @@ static int stlink_write_option_bytes_l0(stlink_t *sl, uint8_t* base, stm32_addr_ * @param base option bytes to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_l4(stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { +static int stlink_write_option_bytes_l4( + stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { uint32_t val; int ret = 0; + (void)addr; + (void)len; - (void) addr; - (void) len; - - /* Write options bytes */ + // write options bytes uint32_t data; - write_uint32((unsigned char*) &data, *(uint32_t*) (base)); + write_uint32((unsigned char*)&data, *(uint32_t*)(base)); WLOG("Writing option bytes 0x%04x\n", data); stlink_write_debug32(sl, STM32L4_FLASH_OPTR, data); - /* Set Options Start bit */ + // set options start bit stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); val |= (1 << STM32L4_FLASH_CR_OPTSTRT); stlink_write_debug32(sl, STM32L4_FLASH_CR, val); - /* Wait for 'busy' bit in FLASH_SR to clear. */ wait_flash_busy(sl); - ret = check_flash_error(sl); - /* apply options bytes immediate */ + // apply options bytes immediate stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); val |= (1 << STM32L4_FLASH_CR_OBL_LAUNCH); stlink_write_debug32(sl, STM32L4_FLASH_CR, val); - return ret; + return(ret); } @@ -3096,25 +3167,24 @@ static int stlink_write_option_bytes_l4(stlink_t *sl, uint8_t* base, stm32_addr_ * @param option_byte value to write * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_f4(stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { +static int stlink_write_option_bytes_f4( + stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { uint32_t option_byte; int ret = 0; + (void)addr; + (void)len; - (void) addr; - (void) len; - - write_uint32((unsigned char*) &option_byte, *(uint32_t*) (base)); + write_uint32((unsigned char*)&option_byte, *(uint32_t*)(base)); - /* write option byte, ensuring we dont lock opt, and set strt bit */ - stlink_write_debug32(sl, FLASH_F4_OPTCR, (option_byte & ~(1 << FLASH_F4_OPTCR_LOCK)) | (1 << FLASH_F4_OPTCR_START)); + // write option byte, ensuring we dont lock opt, and set strt bit + stlink_write_debug32(sl, FLASH_F4_OPTCR, + (option_byte & ~(1 << FLASH_F4_OPTCR_LOCK)) | (1 << FLASH_F4_OPTCR_START)); wait_flash_busy(sl); - ret = check_flash_error(sl); - /* option bytes are reloaded at reset only, no obl. */ - - return ret; + // option bytes are reloaded at reset only, no obl. */ + return(ret); } /** @@ -3124,7 +3194,7 @@ static int stlink_write_option_bytes_f4(stlink_t *sl, uint8_t* base, stm32_addr_ * @return 0 on success, -ve on failure. */ int stlink_read_option_bytes_Gx(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, option_byte); + return(stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, option_byte)); } /** @@ -3134,7 +3204,7 @@ int stlink_read_option_bytes_Gx(stlink_t *sl, uint32_t* option_byte) { * @return 0 on success, -ve on failure. */ int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_debug32(sl, FLASH_F2_OPT_CR, option_byte); + return(stlink_read_debug32(sl, FLASH_F2_OPT_CR, option_byte)); } /** @@ -3144,16 +3214,16 @@ int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte) { * @return 0 on success, -ve on failure. */ int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_debug32(sl, FLASH_F4_OPTCR, option_byte); + return(stlink_read_debug32(sl, FLASH_F4_OPTCR, option_byte)); } /** * Read first option bytes -* @param sl -* @param option_byte option value -* @return 0 on success, -ve on failure. -*/ + * @param sl + * @param option_byte option value + * @return 0 on success, -ve on failure. + */ int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t* option_byte) { - return stlink_read_debug32(sl, sl->option_base, option_byte); + return(stlink_read_debug32(sl, sl->option_base, option_byte)); } /** @@ -3162,25 +3232,24 @@ int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t* option_byte) { * @param option_byte option value * @return 0 on success, -ve on failure. */ -int stlink_read_option_bytes32(stlink_t *sl, uint32_t* option_byte) -{ +int stlink_read_option_bytes32(stlink_t *sl, uint32_t* option_byte) { if (sl->option_base == 0) { ELOG("Option bytes read is currently not supported for connected chip\n"); - return -1; + return(-1); } switch (sl->chip_id) { - case STLINK_CHIPID_STM32_F2: - return stlink_read_option_bytes_f2(sl, option_byte); - case STLINK_CHIPID_STM32_F446: - return stlink_read_option_bytes_f4(sl, option_byte); - case STLINK_CHIPID_STM32_G0_CAT1: - case STLINK_CHIPID_STM32_G0_CAT2: - case STLINK_CHIPID_STM32_G4_CAT2: - case STLINK_CHIPID_STM32_G4_CAT3: - return stlink_read_option_bytes_Gx(sl, option_byte); - default: - return stlink_read_option_bytes_generic(sl, option_byte); + case STLINK_CHIPID_STM32_F2: + return(stlink_read_option_bytes_f2(sl, option_byte)); + case STLINK_CHIPID_STM32_F446: + return(stlink_read_option_bytes_f4(sl, option_byte)); + case STLINK_CHIPID_STM32_G0_CAT1: + case STLINK_CHIPID_STM32_G0_CAT2: + case STLINK_CHIPID_STM32_G4_CAT2: + case STLINK_CHIPID_STM32_G4_CAT3: + return(stlink_read_option_bytes_Gx(sl, option_byte)); + default: + return(stlink_read_option_bytes_generic(sl, option_byte)); } } @@ -3190,10 +3259,9 @@ int stlink_read_option_bytes32(stlink_t *sl, uint32_t* option_byte) * @param option_byte value to write * @return 0 on success, -ve on failure. */ -int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) -{ +int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) { WLOG("About to write option byte %#10x to target.\n", option_byte); - return stlink_write_option_bytes(sl, sl->option_base, (uint8_t *) &option_byte, 4); + return(stlink_write_option_bytes(sl, sl->option_base, (uint8_t *)&option_byte, 4)); } /** @@ -3203,66 +3271,65 @@ int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) * @param base option bytes to write * @return 0 on success, -ve on failure. */ -int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len) -{ +int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len) { int ret = -1; if (sl->option_base == 0) { ELOG("Option bytes writing is currently not supported for connected chip\n"); - return -1; + return(-1); } if ((addr < sl->option_base) || addr > sl->option_base + sl->option_size) { ELOG("Option bytes start address out of Option bytes range\n"); - return -1; + return(-1); } if (addr + len > sl->option_base + sl->option_size) { ELOG("Option bytes data too long\n"); - return -1; + return(-1); } wait_flash_busy(sl); if (unlock_flash_if(sl)) { ELOG("Flash unlock failed! System reset required to be able to unlock it again!\n"); - return -1; + return(-1); } if (unlock_flash_option_if(sl)) { ELOG("Flash option unlock failed!\n"); - return -1; + return(-1); } switch (sl->flash_type) { - case STLINK_FLASH_TYPE_F4: - ret = stlink_write_option_bytes_f4(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_L0: - ret = stlink_write_option_bytes_l0(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_L4: - ret = stlink_write_option_bytes_l4(sl, base, addr, len); - break; - case STLINK_FLASH_TYPE_G0: - case STLINK_FLASH_TYPE_G4: - ret = stlink_write_option_bytes_gx(sl, base, addr, len); - break; - default: - ELOG("Option bytes writing is currently not implemented for connected chip\n"); - break; + case STLINK_FLASH_TYPE_F4: + ret = stlink_write_option_bytes_f4(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_L0: + ret = stlink_write_option_bytes_l0(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_L4: + ret = stlink_write_option_bytes_l4(sl, base, addr, len); + break; + case STLINK_FLASH_TYPE_G0: + case STLINK_FLASH_TYPE_G4: + ret = stlink_write_option_bytes_gx(sl, base, addr, len); + break; + default: + ELOG("Option bytes writing is currently not implemented for connected chip\n"); + break; } - if (ret) + if (ret) { ELOG("Flash option write failed!\n"); - else - ILOG("Wrote %d option bytes to %#010x!\n", len, addr); + } else { + ILOG("Wrote %d option bytes to %#010x!\n", len, addr); + } - /* Re-lock flash. */ lock_flash_option(sl); lock_flash(sl); - return ret; + return(ret); } /** @@ -3273,21 +3340,22 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, ui * @return 0 on success, -ve on failure. */ int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr) { - /* write the file in flash at addr */ + /* Write the file in flash at addr */ int err; mapped_file_t mf = MAPPED_FILE_INITIALIZER; if (map_file(&mf, path) == -1) { ELOG("map_file() == -1\n"); - return -1; + return(-1); } printf("file %s ", path); md5_calculate(&mf); stlink_checksum(&mf); - err = stlink_write_option_bytes(sl, addr, mf.base, (uint32_t) mf.len); + err = stlink_write_option_bytes(sl, addr, mf.base, (uint32_t)mf.len); stlink_fwrite_finalize(sl, addr); unmap_file(&mf); - return err; + + return(err); } diff --git a/src/flash_loader.c b/src/flash_loader.c deleted file mode 100644 index a2c5879ce..000000000 --- a/src/flash_loader.c +++ /dev/null @@ -1,392 +0,0 @@ -#include -#include -#include - -#include - -#define FLASH_REGS_BANK2_OFS 0x40 -#define FLASH_BANK2_START_ADDR 0x08080000 - -/* DO NOT MODIFY SOURCECODE DIRECTLY, EDIT ASSEMBLY FILES INSTEAD */ - - /* flashloaders/stm32f0.s -- compiled with thumb2 */ - static const uint8_t loader_code_stm32vl[] = { - 0x16, 0x4f, 0x3c, 0x68, - 0x16, 0x4f, 0x3e, 0x68, - 0x36, 0x19, 0x16, 0x4f, - 0x3d, 0x68, 0x2d, 0x19, - 0x4f, 0xf0, 0x01, 0x07, - 0x33, 0x68, 0x3b, 0x43, - 0x33, 0x60, 0x03, 0x88, - 0x0b, 0x80, 0x4f, 0xf0, - 0x02, 0x07, 0xc0, 0x19, - 0xc9, 0x19, 0x4f, 0xf0, - 0x01, 0x07, 0x2b, 0x68, - 0x3b, 0x42, 0xfa, 0xd0, - 0x4f, 0xf0, 0x04, 0x07, - 0x3b, 0x42, 0x04, 0xd1, - 0x4f, 0xf0, 0x01, 0x07, - 0xd2, 0x1b, 0x00, 0x2a, - 0xe6, 0xd1, 0x4f, 0xf0, - 0x01, 0x07, 0x33, 0x68, - 0xbb, 0x43, 0x33, 0x60, - 0x00, 0xbe, 0x00, 0xbf, - 0x00, 0x20, 0x02, 0x40, - 0x10, 0x00, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x00, 0x20, - 0x54, 0x00, 0x00, 0x20, - 0x58, 0x00, 0x00, 0x20 - }; - - /* flashloaders/stm32f0.s -- thumb1 only, same sequence as for STM32VL, bank ignored */ - static const uint8_t loader_code_stm32f0[] = { - 0xc0, 0x46, 0xc0, 0x46, - 0x13, 0x4f, 0x3c, 0x68, - 0x13, 0x4f, 0x3e, 0x68, - 0x36, 0x19, 0x13, 0x4f, - 0x3d, 0x68, 0x2d, 0x19, - 0x12, 0x4f, 0x33, 0x68, - 0x3b, 0x43, 0x33, 0x60, - 0x03, 0x88, 0x0b, 0x80, - 0x10, 0x4f, 0xc0, 0x19, - 0xc9, 0x19, 0x0e, 0x4f, - 0x2b, 0x68, 0x3b, 0x42, - 0xfb, 0xd0, 0x0e, 0x4f, - 0x3b, 0x42, 0x03, 0xd1, - 0x0a, 0x4f, 0xd2, 0x1b, - 0x00, 0x2a, 0xeb, 0xd1, - 0x08, 0x4f, 0x33, 0x68, - 0xbb, 0x43, 0x33, 0x60, - 0x00, 0xbe, 0xc0, 0x46, - 0x00, 0x20, 0x02, 0x40, - 0x10, 0x00, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x20, - 0x4c, 0x00, 0x00, 0x20, - 0x50, 0x00, 0x00, 0x20, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00 - }; - - static const uint8_t loader_code_stm32l[] = { - // flashloaders/stm32lx.s - - 0x03, 0x68, 0x0b, 0x60, - 0x4f, 0xf0, 0x04, 0x07, - 0x38, 0x44, 0x39, 0x44, - 0x4f, 0xf0, 0x01, 0x07, - 0xd2, 0x1b, 0x00, 0x2a, - 0xf4, 0xd1, 0x00, 0xbe, - }; - - static const uint8_t loader_code_stm32f4[] = { - // flashloaders/stm32f4.s - - 0xdf, 0xf8, 0x28, 0xc0, - 0xdf, 0xf8, 0x28, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x0b, 0x60, 0x00, 0xf1, - 0x04, 0x00, 0x01, 0xf1, - 0x04, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xf0, 0xd1, - 0x00, 0xbe, 0x00, 0xbf, - 0x00, 0x3c, 0x02, 0x40, - 0x0e, 0x00, 0x00, 0x00 - }; - - static const uint8_t loader_code_stm32f4_lv[] = { - // flashloaders/stm32f4lv.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x4f, 0xea, - 0x82, 0x02, 0x03, 0x78, - 0x0b, 0x70, 0x00, 0xf1, - 0x01, 0x00, 0x01, 0xf1, - 0x01, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xf0, 0xd1, - 0x00, 0xbe, 0x00, 0xbf, - 0x00, 0x3c, 0x02, 0x40, - 0x0e, 0x00, 0x00, 0x00 - }; - - static const uint8_t loader_code_stm32l4[] = { - // flashloaders/stm32l4.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x44, 0x68, 0x0b, 0x60, - 0x4c, 0x60, 0x00, 0xf1, - 0x08, 0x00, 0x01, 0xf1, - 0x08, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, - 0x00, 0xbe, 0x00, 0xbf, - 0x00, 0x20, 0x02, 0x40, - 0x12, 0x00, 0x00, 0x00 - }; - - static const uint8_t loader_code_stm32f7[] = { - // flashloaders/stm32f7.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x0b, 0x60, 0x00, 0xf1, - 0x04, 0x00, 0x01, 0xf1, - 0x04, 0x01, 0xbf, 0xf3, - 0x4f, 0x8f, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, - 0x00, 0xbe, 0x00, 0xbf, - 0x00, 0x3c, 0x02, 0x40, - 0x0e, 0x00, 0x00, 0x00 - }; - - static const uint8_t loader_code_stm32f7_lv[] = { - // flashloaders/stm32f7lv.s - 0xdf, 0xf8, 0x30, 0xc0, - 0xdf, 0xf8, 0x30, 0xa0, - 0xe2, 0x44, 0x4f, 0xea, - 0x82, 0x02, 0x03, 0x78, - 0x0b, 0x70, 0x00, 0xf1, - 0x01, 0x00, 0x01, 0xf1, - 0x01, 0x01, 0xbf, 0xf3, - 0x4f, 0x8f, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, - 0x00, 0xbe, 0x00, 0xbf, - 0x00, 0x3c, 0x02, 0x40, - 0x0e, 0x00, 0x00, 0x00 - }; - - - -int stlink_flash_loader_init(stlink_t *sl, flash_loader_t *fl) -{ - size_t size = 0; - - /* allocate the loader in sram */ - if (stlink_flash_loader_write_to_sram(sl, &fl->loader_addr, &size) == -1) { - WLOG("Failed to write flash loader to sram!\n"); - return -1; - } - - /* allocate a one page buffer in sram right after loader */ - fl->buf_addr = fl->loader_addr + (uint32_t) size; - ILOG("Successfully loaded flash loader in sram\n"); - - return 0; -} - -static int loader_v_dependent_assignment(stlink_t *sl, - const uint8_t **loader_code, size_t *loader_size, - const uint8_t *high_v_loader, size_t high_v_loader_size, - const uint8_t *low_v_loader, size_t low_v_loader_size) -{ - int retval = 0; - - if ( sl->version.stlink_v == 1){ - printf("STLINK V1 cannot read voltage, defaulting to 32-bit writes\n"); - *loader_code = high_v_loader; - *loader_size = high_v_loader_size; - } - else { - int voltage = stlink_target_voltage(sl); - if (voltage == -1) { - retval = -1; - printf("Failed to read Target voltage\n"); - } - else { - if (voltage > 2700) { - *loader_code = high_v_loader; - *loader_size = high_v_loader_size; - } else { - *loader_code = low_v_loader; - *loader_size = low_v_loader_size; - } - } - } - return retval; -} - -int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) -{ - const uint8_t* loader_code; - size_t loader_size; - - if (sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM || - sl->chip_id == STLINK_CHIPID_STM32_L1_CAT2 || - sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM_PLUS || - sl->chip_id == STLINK_CHIPID_STM32_L1_HIGH || - sl->chip_id == STLINK_CHIPID_STM32_L152_RE || - sl->chip_id == STLINK_CHIPID_STM32_L011 || - sl->chip_id == STLINK_CHIPID_STM32_L0 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || - sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2) { /* stm32l */ - loader_code = loader_code_stm32l; - loader_size = sizeof(loader_code_stm32l); - } else if (sl->core_id == STM32VL_CORE_ID || - sl->chip_id == STLINK_CHIPID_STM32_F1_MEDIUM || - sl->chip_id == STLINK_CHIPID_STM32_F3 || - sl->chip_id == STLINK_CHIPID_STM32_F3_SMALL || - sl->chip_id == STLINK_CHIPID_STM32_F303_HIGH || - sl->chip_id == STLINK_CHIPID_STM32_F37x || - sl->chip_id == STLINK_CHIPID_STM32_F334) { - loader_code = loader_code_stm32vl; - loader_size = sizeof(loader_code_stm32vl); - } else if (sl->chip_id == STLINK_CHIPID_STM32_F2 || - sl->chip_id == STLINK_CHIPID_STM32_F4 || - sl->chip_id == STLINK_CHIPID_STM32_F4_DE || - sl->chip_id == STLINK_CHIPID_STM32_F4_LP || - sl->chip_id == STLINK_CHIPID_STM32_F4_HD || - sl->chip_id == STLINK_CHIPID_STM32_F4_DSI || - sl->chip_id == STLINK_CHIPID_STM32_F410 || - sl->chip_id == STLINK_CHIPID_STM32_F411RE || - sl->chip_id == STLINK_CHIPID_STM32_F412 || - sl->chip_id == STLINK_CHIPID_STM32_F413 || - sl->chip_id == STLINK_CHIPID_STM32_F446 - ) { - int retval; - retval = loader_v_dependent_assignment(sl, - &loader_code, &loader_size, - loader_code_stm32f4, sizeof(loader_code_stm32f4), - loader_code_stm32f4_lv, sizeof(loader_code_stm32f4_lv)); - if (retval == -1) { - return retval; - } - } else if (sl->core_id == STM32F7_CORE_ID || - sl->chip_id == STLINK_CHIPID_STM32_F7 || - sl->chip_id == STLINK_CHIPID_STM32_F7XXXX || - sl->chip_id == STLINK_CHIPID_STM32_F72XXX - ) { - int retval; - retval = loader_v_dependent_assignment(sl, - &loader_code, &loader_size, - loader_code_stm32f7, sizeof(loader_code_stm32f7), - loader_code_stm32f7_lv, sizeof(loader_code_stm32f7_lv)); - if (retval == -1) { - return retval; - } - } else if (sl->chip_id == STLINK_CHIPID_STM32_F0 || - sl->chip_id == STLINK_CHIPID_STM32_F04 || - sl->chip_id == STLINK_CHIPID_STM32_F0_CAN || - sl->chip_id == STLINK_CHIPID_STM32_F0_SMALL || - sl->chip_id == STLINK_CHIPID_STM32_F09X) { - loader_code = loader_code_stm32f0; - loader_size = sizeof(loader_code_stm32f0); - } else if ((sl->chip_id == STLINK_CHIPID_STM32_L4) || - (sl->chip_id == STLINK_CHIPID_STM32_L41X) || - (sl->chip_id == STLINK_CHIPID_STM32_L43X) || - (sl->chip_id == STLINK_CHIPID_STM32_L46X) || - (sl->chip_id == STLINK_CHIPID_STM32_L4RX) || - (sl->chip_id == STLINK_CHIPID_STM32_L496X)) - { - loader_code = loader_code_stm32l4; - loader_size = sizeof(loader_code_stm32l4); - } else { - ELOG("unknown coreid, not sure what flash loader to use, aborting! coreid: %x, chipid: %x\n", sl->core_id, sl->chip_id); - return -1; - } - - memcpy(sl->q_buf, loader_code, loader_size); - int ret = stlink_write_mem32(sl, sl->sram_base, loader_size); - if (ret) - return ret; - - *addr = sl->sram_base; - *size = loader_size; - - /* success */ - return 0; -} - -int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size) -{ - struct stlink_reg rr; - int i = 0; - size_t count = 0; - uint32_t flash_base = 0; - - DLOG("Running flash loader, write address:%#x, size: %u\n", target, (unsigned int)size); - // FIXME This can never return -1 - if (write_buffer_to_sram(sl, fl, buf, size) == -1) { - // IMPOSSIBLE! - ELOG("write_buffer_to_sram() == -1\n"); - return -1; - } - - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { - count = size / sizeof(uint16_t); - if (size % sizeof(uint16_t)) - ++count; - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4 || - sl->flash_type == STLINK_FLASH_TYPE_L0) { - count = size / sizeof(uint32_t); - if (size % sizeof(uint32_t)) - ++count; - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - count = size / sizeof(uint64_t); - if (size % sizeof(uint64_t)) - ++count; - } - - if ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (target >= FLASH_BANK2_START_ADDR)) { - flash_base = FLASH_REGS_BANK2_OFS; - } - - /* setup core */ - stlink_write_reg(sl, fl->buf_addr, 0); /* source */ - stlink_write_reg(sl, target, 1); /* target */ - stlink_write_reg(sl, (uint32_t) count, 2); /* count */ - stlink_write_reg(sl, flash_base, 3); /* flash register base, only used on VL/F1_XL, but harmless for others */ - stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */ - - /* run loader */ - stlink_run(sl); - -// This piece of code used to try to spin for .1 second by waiting -// doing 10000 rounds of 10 microseconds. But because this usually runs -// on Unix-like OSes, the 10 microseconds get rounded up to the "tick" -// (actually almost two ticks) of the system. 1 milisecond. Thus, the -// ten thousand attempts, when "something goes wrong" that requires -// the error message "flash loader run error" would wait for something -// like 20 seconds before coming up with the error. -// by increasing the sleep-per-round to the same order-of-magnitude as -// the tick-rounding that the OS uses, the wait until the error message is -// reduced to the same order of magnitude as what was intended. -- REW. -#define WAIT_ROUNDS 100 - /* wait until done (reaches breakpoint) */ - for (i = 0; i < WAIT_ROUNDS; i++) { - usleep(1000); - if (stlink_is_core_halted(sl)) - break; - } - - if (i >= WAIT_ROUNDS) { - ELOG("flash loader run error\n"); - return -1; - } - - /* check written byte count */ - stlink_read_reg(sl, 2, &rr); - if (rr.r[2] != 0) { - ELOG("write error, count == %u\n", rr.r[2]); - return -1; - } - - return 0; -} diff --git a/src/getopt/getopt.c b/src/getopt/getopt.c deleted file mode 100644 index 5dd45bff7..000000000 --- a/src/getopt/getopt.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include - -#include "getopt.h" - -#if !defined(_MSC_VER) -const int no_argument = 0; -const int required_argument = 1; -const int optional_argument = 2; -#endif - -char* optarg; -int optopt; -/* The variable optind [...] shall be initialized to 1 by the system. */ -int optind = 1; -int opterr; - -static char* optcursor = NULL; - -/* Implemented based on [1] and [2] for optional arguments. - optopt is handled FreeBSD-style, per [3]. - Other GNU and FreeBSD extensions are purely accidental. - -[1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html -[2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html -[3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE -*/ -int getopt(int argc, char* const argv[], const char* optstring) { - int optchar = -1; - const char* optdecl = NULL; - - optarg = NULL; - opterr = 0; - optopt = 0; - - /* Unspecified, but we need it to avoid overrunning the argv bounds. */ - if (optind >= argc) - goto no_more_optchars; - - /* If, when getopt() is called argv[optind] is a null pointer, getopt() - shall return -1 without changing optind. */ - if (argv[optind] == NULL) - goto no_more_optchars; - - /* If, when getopt() is called *argv[optind] is not the character '-', - getopt() shall return -1 without changing optind. */ - if (*argv[optind] != '-') - goto no_more_optchars; - - /* If, when getopt() is called argv[optind] points to the string "-", - getopt() shall return -1 without changing optind. */ - if (strcmp(argv[optind], "-") == 0) - goto no_more_optchars; - - /* If, when getopt() is called argv[optind] points to the string "--", - getopt() shall return -1 after incrementing optind. */ - if (strcmp(argv[optind], "--") == 0) { - ++optind; - goto no_more_optchars; - } - - if (optcursor == NULL || *optcursor == '\0') - optcursor = argv[optind] + 1; - - optchar = *optcursor; - - /* FreeBSD: The variable optopt saves the last known option character - returned by getopt(). */ - optopt = optchar; - - /* The getopt() function shall return the next option character (if one is - found) from argv that matches a character in optstring, if there is - one that matches. */ - optdecl = strchr(optstring, optchar); - if (optdecl) { - /* [I]f a character is followed by a colon, the option takes an - argument. */ - if (optdecl[1] == ':') { - optarg = ++optcursor; - if (*optarg == '\0') { - /* GNU extension: Two colons mean an option takes an - optional arg; if there is text in the current argv-element - (i.e., in the same word as the option name itself, for example, - "-oarg"), then it is returned in optarg, otherwise optarg is set - to zero. */ - if (optdecl[2] != ':') { - /* If the option was the last character in the string pointed to by - an element of argv, then optarg shall contain the next element - of argv, and optind shall be incremented by 2. If the resulting - value of optind is greater than argc, this indicates a missing - option-argument, and getopt() shall return an error indication. - - Otherwise, optarg shall point to the string following the - option character in that element of argv, and optind shall be - incremented by 1. - */ - if (++optind < argc) { - optarg = argv[optind]; - } else { - /* If it detects a missing option-argument, it shall return the - colon character ( ':' ) if the first character of optstring - was a colon, or a question-mark character ( '?' ) otherwise. - */ - optarg = NULL; - optchar = (optstring[0] == ':') ? ':' : '?'; - } - } else { - optarg = NULL; - } - } - - optcursor = NULL; - } - } else { - /* If getopt() encounters an option character that is not contained in - optstring, it shall return the question-mark ( '?' ) character. */ - optchar = '?'; - } - - if (optcursor == NULL || *++optcursor == '\0') - ++optind; - - return optchar; - -no_more_optchars: - optcursor = NULL; - return -1; -} - -/* Implementation based on [1]. - -[1] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html -*/ -int getopt_long(int argc, char* const argv[], const char* optstring, - const struct option* longopts, int* longindex) { - const struct option* o = longopts; - const struct option* match = NULL; - int num_matches = 0; - size_t argument_name_length = 0; - const char* current_argument = NULL; - int retval = -1; - - optarg = NULL; - optopt = 0; - - if (optind >= argc) - return -1; - - if (strlen(argv[optind]) < 3 || strncmp(argv[optind], "--", 2) != 0) - return getopt(argc, argv, optstring); - - /* It's an option; starts with -- and is longer than two chars. */ - current_argument = argv[optind] + 2; - argument_name_length = strcspn(current_argument, "="); - for (; o->name; ++o) { - if (strncmp(o->name, current_argument, argument_name_length) == 0) { - match = o; - ++num_matches; - } - } - - if (num_matches == 1) { - /* If longindex is not NULL, it points to a variable which is set to the - index of the long option relative to longopts. */ - if (longindex) - *longindex = (match - longopts); - - /* If flag is NULL, then getopt_long() shall return val. - Otherwise, getopt_long() returns 0, and flag shall point to a variable - which shall be set to val if the option is found, but left unchanged if - the option is not found. */ - if (match->flag) - *(match->flag) = match->val; - - retval = match->flag ? 0 : match->val; - - if (match->has_arg != no_argument) { - optarg = strchr(argv[optind], '='); - if (optarg != NULL) - ++optarg; - - if (match->has_arg == required_argument) { - /* Only scan the next argv for required arguments. Behavior is not - specified, but has been observed with Ubuntu and Mac OSX. */ - if (optarg == NULL && ++optind < argc) { - optarg = argv[optind]; - } - - if (optarg == NULL) - retval = ':'; - } - } else if (strchr(argv[optind], '=')) { - /* An argument was provided to a non-argument option. - I haven't seen this specified explicitly, but both GNU and BSD-based - implementations show this behavior. - */ - retval = '?'; - } - } else { - /* Unknown option or ambiguous match. */ - retval = '?'; - } - - ++optind; - return retval; -} diff --git a/src/md5.c b/src/md5.c deleted file mode 100755 index 521c52969..000000000 --- a/src/md5.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Retrieved from https://github.com/WaterJuice/WjCryptLib - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// WjCryptLib_Md5 -// -// Implementation of MD5 hash function. Originally written by Alexander Peslyak. Modified by WaterJuice retaining -// Public Domain license. -// -// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// IMPORTS -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include - -#include "md5.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// INTERNAL FUNCTIONS -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// F, G, H, I -// -// The basic MD5 functions. F and G are optimised compared to their RFC 1321 definitions for architectures that lack -// an AND-NOT instruction, just like in Colin Plumb's implementation. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define F( x, y, z ) ( (z) ^ ((x) & ((y) ^ (z))) ) -#define G( x, y, z ) ( (y) ^ ((z) & ((x) ^ (y))) ) -#define H( x, y, z ) ( (x) ^ (y) ^ (z) ) -#define I( x, y, z ) ( (y) ^ ((x) | ~(z)) ) - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// STEP -// -// The MD5 transformation for all four rounds. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define STEP( f, a, b, c, d, x, t, s ) \ - (a) += f((b), (c), (d)) + (x) + (t); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ - (a) += (b); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// TransformFunction -// -// This processes one or more 64-byte data blocks, but does NOT update the bit counters. There are no alignment -// requirements. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void* - TransformFunction - ( - Md5Context* ctx, - void const* data, - uintmax_t size - ) -{ - uint8_t* ptr; - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - uint32_t saved_a; - uint32_t saved_b; - uint32_t saved_c; - uint32_t saved_d; - - #define GET(n) (ctx->block[(n)]) - #define SET(n) (ctx->block[(n)] = \ - ((uint32_t)ptr[(n)*4 + 0] << 0) \ - | ((uint32_t)ptr[(n)*4 + 1] << 8 ) \ - | ((uint32_t)ptr[(n)*4 + 2] << 16) \ - | ((uint32_t)ptr[(n)*4 + 3] << 24) ) - - ptr = (uint8_t*)data; - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - do - { - saved_a = a; - saved_b = b; - saved_c = c; - saved_d = d; - - // Round 1 - STEP( F, a, b, c, d, SET(0), 0xd76aa478, 7 ) - STEP( F, d, a, b, c, SET(1), 0xe8c7b756, 12 ) - STEP( F, c, d, a, b, SET(2), 0x242070db, 17 ) - STEP( F, b, c, d, a, SET(3), 0xc1bdceee, 22 ) - STEP( F, a, b, c, d, SET(4), 0xf57c0faf, 7 ) - STEP( F, d, a, b, c, SET(5), 0x4787c62a, 12 ) - STEP( F, c, d, a, b, SET(6), 0xa8304613, 17 ) - STEP( F, b, c, d, a, SET(7), 0xfd469501, 22 ) - STEP( F, a, b, c, d, SET(8 ), 0x698098d8, 7 ) - STEP( F, d, a, b, c, SET(9 ), 0x8b44f7af, 12 ) - STEP( F, c, d, a, b, SET(10 ), 0xffff5bb1, 17 ) - STEP( F, b, c, d, a, SET(11 ), 0x895cd7be, 22 ) - STEP( F, a, b, c, d, SET(12 ), 0x6b901122, 7 ) - STEP( F, d, a, b, c, SET(13 ), 0xfd987193, 12 ) - STEP( F, c, d, a, b, SET(14 ), 0xa679438e, 17 ) - STEP( F, b, c, d, a, SET(15 ), 0x49b40821, 22 ) - - // Round 2 - STEP( G, a, b, c, d, GET(1), 0xf61e2562, 5 ) - STEP( G, d, a, b, c, GET(6), 0xc040b340, 9 ) - STEP( G, c, d, a, b, GET(11), 0x265e5a51, 14 ) - STEP( G, b, c, d, a, GET(0), 0xe9b6c7aa, 20 ) - STEP( G, a, b, c, d, GET(5), 0xd62f105d, 5 ) - STEP( G, d, a, b, c, GET(10), 0x02441453, 9 ) - STEP( G, c, d, a, b, GET(15), 0xd8a1e681, 14 ) - STEP( G, b, c, d, a, GET(4), 0xe7d3fbc8, 20 ) - STEP( G, a, b, c, d, GET(9), 0x21e1cde6, 5 ) - STEP( G, d, a, b, c, GET(14), 0xc33707d6, 9 ) - STEP( G, c, d, a, b, GET(3), 0xf4d50d87, 14 ) - STEP( G, b, c, d, a, GET(8), 0x455a14ed, 20 ) - STEP( G, a, b, c, d, GET(13), 0xa9e3e905, 5 ) - STEP( G, d, a, b, c, GET(2), 0xfcefa3f8, 9 ) - STEP( G, c, d, a, b, GET(7), 0x676f02d9, 14 ) - STEP( G, b, c, d, a, GET(12), 0x8d2a4c8a, 20 ) - - // Round 3 - STEP( H, a, b, c, d, GET(5), 0xfffa3942, 4 ) - STEP( H, d, a, b, c, GET(8), 0x8771f681, 11 ) - STEP( H, c, d, a, b, GET(11), 0x6d9d6122, 16 ) - STEP( H, b, c, d, a, GET(14), 0xfde5380c, 23 ) - STEP( H, a, b, c, d, GET(1), 0xa4beea44, 4 ) - STEP( H, d, a, b, c, GET(4), 0x4bdecfa9, 11 ) - STEP( H, c, d, a, b, GET(7), 0xf6bb4b60, 16 ) - STEP( H, b, c, d, a, GET(10), 0xbebfbc70, 23 ) - STEP( H, a, b, c, d, GET(13), 0x289b7ec6, 4 ) - STEP( H, d, a, b, c, GET(0), 0xeaa127fa, 11 ) - STEP( H, c, d, a, b, GET(3), 0xd4ef3085, 16 ) - STEP( H, b, c, d, a, GET(6), 0x04881d05, 23 ) - STEP( H, a, b, c, d, GET(9), 0xd9d4d039, 4 ) - STEP( H, d, a, b, c, GET(12), 0xe6db99e5, 11 ) - STEP( H, c, d, a, b, GET(15), 0x1fa27cf8, 16 ) - STEP( H, b, c, d, a, GET(2), 0xc4ac5665, 23 ) - - // Round 4 - STEP( I, a, b, c, d, GET(0), 0xf4292244, 6 ) - STEP( I, d, a, b, c, GET(7), 0x432aff97, 10 ) - STEP( I, c, d, a, b, GET(14), 0xab9423a7, 15 ) - STEP( I, b, c, d, a, GET(5), 0xfc93a039, 21 ) - STEP( I, a, b, c, d, GET(12), 0x655b59c3, 6 ) - STEP( I, d, a, b, c, GET(3), 0x8f0ccc92, 10 ) - STEP( I, c, d, a, b, GET(10), 0xffeff47d, 15 ) - STEP( I, b, c, d, a, GET(1), 0x85845dd1, 21 ) - STEP( I, a, b, c, d, GET(8), 0x6fa87e4f, 6 ) - STEP( I, d, a, b, c, GET(15), 0xfe2ce6e0, 10 ) - STEP( I, c, d, a, b, GET(6), 0xa3014314, 15 ) - STEP( I, b, c, d, a, GET(13), 0x4e0811a1, 21 ) - STEP( I, a, b, c, d, GET(4), 0xf7537e82, 6 ) - STEP( I, d, a, b, c, GET(11), 0xbd3af235, 10 ) - STEP( I, c, d, a, b, GET(2), 0x2ad7d2bb, 15 ) - STEP( I, b, c, d, a, GET(9), 0xeb86d391, 21 ) - - a += saved_a; - b += saved_b; - c += saved_c; - d += saved_d; - - ptr += 64; - } while ( size -= 64 ); - - ctx->a = a; - ctx->b = b; - ctx->c = c; - ctx->d = d; - - #undef GET - #undef SET - - return ptr; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// EXPORTED FUNCTIONS -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Initialise -// -// Initialises an MD5 Context. Use this to initialise/reset a context. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Initialise - ( - Md5Context* Context // [out] - ) -{ - Context->a = 0x67452301; - Context->b = 0xefcdab89; - Context->c = 0x98badcfe; - Context->d = 0x10325476; - - Context->lo = 0; - Context->hi = 0; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Update -// -// Adds data to the MD5 context. This will process the data and update the internal state of the context. Keep on -// calling this function until all the data has been added. Then call Md5Finalise to calculate the hash. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Update - ( - Md5Context* Context, // [in out] - void const* Buffer, // [in] - uint32_t BufferSize // [in] - ) -{ - uint32_t saved_lo; - uint32_t used; - uint32_t free; - - saved_lo = Context->lo; - if ( (Context->lo = (saved_lo + BufferSize) & 0x1fffffff) < saved_lo ) - { - Context->hi++; - } - Context->hi += (uint32_t)( BufferSize >> 29 ); - - used = saved_lo & 0x3f; - - if ( used ) - { - free = 64 - used; - - if ( BufferSize < free ) - { - memcpy( &Context->buffer[used], Buffer, BufferSize ); - return; - } - - memcpy( &Context->buffer[used], Buffer, free ); - Buffer = (uint8_t*)Buffer + free; - BufferSize -= free; - TransformFunction(Context, Context->buffer, 64); - } - - if ( BufferSize >= 64 ) - { - Buffer = TransformFunction( Context, Buffer, BufferSize & ~(unsigned long)0x3f ); - BufferSize &= 0x3f; - } - - memcpy( Context->buffer, Buffer, BufferSize ); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Finalise -// -// Performs the final calculation of the hash and returns the digest (16 byte buffer containing 128bit hash). After -// calling this, Md5Initialised must be used to reuse the context. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Finalise - ( - Md5Context* Context, // [in out] - MD5_HASH* Digest // [in] - ) -{ - uint32_t used; - uint32_t free; - - used = Context->lo & 0x3f; - - Context->buffer[used++] = 0x80; - - free = 64 - used; - - if (free < 8) - { - memset( &Context->buffer[used], 0, free ); - TransformFunction( Context, Context->buffer, 64 ); - used = 0; - free = 64; - } - - memset( &Context->buffer[used], 0, free - 8 ); - - Context->lo <<= 3; - Context->buffer[56] = (uint8_t)( Context->lo ); - Context->buffer[57] = (uint8_t)( Context->lo >> 8 ); - Context->buffer[58] = (uint8_t)( Context->lo >> 16 ); - Context->buffer[59] = (uint8_t)( Context->lo >> 24 ); - Context->buffer[60] = (uint8_t)( Context->hi ); - Context->buffer[61] = (uint8_t)( Context->hi >> 8 ); - Context->buffer[62] = (uint8_t)( Context->hi >> 16 ); - Context->buffer[63] = (uint8_t)( Context->hi >> 24 ); - - TransformFunction( Context, Context->buffer, 64 ); - - Digest->bytes[0] = (uint8_t)( Context->a ); - Digest->bytes[1] = (uint8_t)( Context->a >> 8 ); - Digest->bytes[2] = (uint8_t)( Context->a >> 16 ); - Digest->bytes[3] = (uint8_t)( Context->a >> 24 ); - Digest->bytes[4] = (uint8_t)( Context->b ); - Digest->bytes[5] = (uint8_t)( Context->b >> 8 ); - Digest->bytes[6] = (uint8_t)( Context->b >> 16 ); - Digest->bytes[7] = (uint8_t)( Context->b >> 24 ); - Digest->bytes[8] = (uint8_t)( Context->c ); - Digest->bytes[9] = (uint8_t)( Context->c >> 8 ); - Digest->bytes[10] = (uint8_t)( Context->c >> 16 ); - Digest->bytes[11] = (uint8_t)( Context->c >> 24 ); - Digest->bytes[12] = (uint8_t)( Context->d ); - Digest->bytes[13] = (uint8_t)( Context->d >> 8 ); - Digest->bytes[14] = (uint8_t)( Context->d >> 16 ); - Digest->bytes[15] = (uint8_t)( Context->d >> 24 ); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Calculate -// -// Combines Md5Initialise, Md5Update, and Md5Finalise into one function. Calculates the MD5 hash of the buffer. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Calculate - ( - void const* Buffer, // [in] - uint32_t BufferSize, // [in] - MD5_HASH* Digest // [in] - ) -{ - Md5Context context; - - Md5Initialise( &context ); - Md5Update( &context, Buffer, BufferSize ); - Md5Finalise( &context, Digest ); -} diff --git a/src/md5.h b/src/md5.h deleted file mode 100755 index 5ef252221..000000000 --- a/src/md5.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Retrieved from https://github.com/WaterJuice/WjCryptLib - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// WjCryptLib_Md5 -// -// Implementation of MD5 hash function. Originally written by Alexander Peslyak. Modified by WaterJuice retaining -// Public Domain license. -// -// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// IMPORTS -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include -#include - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// TYPES -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Md5Context - This must be initialised using Md5Initialised. Do not modify the contents of this structure directly. -typedef struct -{ - uint32_t lo; - uint32_t hi; - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - uint8_t buffer[64]; - uint32_t block[16]; -} Md5Context; - -#define MD5_HASH_SIZE ( 128 / 8 ) - -typedef struct -{ - uint8_t bytes [MD5_HASH_SIZE]; -} MD5_HASH; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// PUBLIC FUNCTIONS -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Initialise -// -// Initialises an MD5 Context. Use this to initialise/reset a context. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Initialise - ( - Md5Context* Context // [out] - ); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Update -// -// Adds data to the MD5 context. This will process the data and update the internal state of the context. Keep on -// calling this function until all the data has been added. Then call Md5Finalise to calculate the hash. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Update - ( - Md5Context* Context, // [in out] - void const* Buffer, // [in] - uint32_t BufferSize // [in] - ); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Finalise -// -// Performs the final calculation of the hash and returns the digest (16 byte buffer containing 128bit hash). After -// calling this, Md5Initialised must be used to reuse the context. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Finalise - ( - Md5Context* Context, // [in out] - MD5_HASH* Digest // [in] - ); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Md5Calculate -// -// Combines Md5Initialise, Md5Update, and Md5Finalise into one function. Calculates the MD5 hash of the buffer. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - Md5Calculate - ( - void const* Buffer, // [in] - uint32_t BufferSize, // [in] - MD5_HASH* Digest // [in] - ); diff --git a/src/mingw/mingw.c b/src/mingw/mingw.c deleted file mode 100644 index 646fca238..000000000 --- a/src/mingw/mingw.c +++ /dev/null @@ -1,309 +0,0 @@ -#if defined(__MINGW32__) || defined(_MSC_VER) - -#include "mingw.h" - -#undef socket -#undef connect -#undef accept -#undef shutdown - -#include -#include -#include - -int win32_poll(struct pollfd *fds, unsigned int nfds, int timo) -{ - struct timeval timeout, *toptr; - fd_set ifds, ofds, efds, *ip, *op; - unsigned int i; - int rc; - - /* Set up the file-descriptor sets in ifds, ofds and efds. */ -#ifdef _MSC_VER -#pragma warning(disable: 4548) -#endif - FD_ZERO(&ifds); - FD_ZERO(&ofds); - FD_ZERO(&efds); - for (i = 0, op = ip = 0; i < nfds; ++i) { - fds[i].revents = 0; - if (fds[i].events & (POLLIN|POLLPRI)) { - ip = &ifds; - FD_SET(fds[i].fd, ip); - } - if (fds[i].events & POLLOUT) { - op = &ofds; - FD_SET(fds[i].fd, op); - } - FD_SET(fds[i].fd, &efds); - } -#ifdef _MSC_VER -#pragma warning(default: 4548) -#endif - - /* Set up the timeval structure for the timeout parameter */ - if (timo < 0) { - toptr = 0; - } else { - toptr = &timeout; - timeout.tv_sec = timo / 1000; - timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000; - } - -#ifdef DEBUG_POLL - printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n", - (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op); -#endif - rc = select(0, ip, op, &efds, toptr); -#ifdef DEBUG_POLL - printf("Exiting select rc=%d\n", rc); -#endif - - if (rc <= 0) - return rc; - - if (rc > 0) { - for ( i = 0; i < nfds; ++i) { - int fd = fds[i].fd; - if (fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds)) - fds[i].revents |= POLLIN; - if (fds[i].events & POLLOUT && FD_ISSET(fd, &ofds)) - fds[i].revents |= POLLOUT; - if (FD_ISSET(fd, &efds)) - /* Some error was detected ... should be some way to know. */ - fds[i].revents |= POLLHUP; -#ifdef DEBUG_POLL - printf("%d %d %d revent = %x\n", - FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds), - fds[i].revents - ); -#endif - } - } - return rc; -} -static void -set_connect_errno(int winsock_err) -{ - switch(winsock_err) { - case WSAEINVAL: - case WSAEALREADY: - case WSAEWOULDBLOCK: - errno = EINPROGRESS; - break; - default: - errno = winsock_err; - break; - } -} - -static void -set_socket_errno(int winsock_err) -{ - switch(winsock_err) { - case WSAEWOULDBLOCK: - errno = EAGAIN; - break; - default: - errno = winsock_err; - break; - } -} -/* - * A wrapper around the socket() function. The purpose of this wrapper - * is to ensure that the global errno symbol is set if an error occurs, - * even if we are using winsock. - */ -SOCKET -win32_socket(int domain, int type, int protocol) -{ - SOCKET fd = socket(domain, type, protocol); - if (fd == INVALID_SOCKET) { - set_socket_errno(WSAGetLastError()); - } - return fd; -} -/* - * A wrapper around the connect() function. The purpose of this wrapper - * is to ensure that the global errno symbol is set if an error occurs, - * even if we are using winsock. - */ -int -win32_connect(SOCKET fd, struct sockaddr *addr, socklen_t addr_len) -{ - int rc = connect(fd, addr, addr_len); - assert(rc == 0 || rc == SOCKET_ERROR); - if (rc == SOCKET_ERROR) { - set_connect_errno(WSAGetLastError()); - } - return rc; -} - -/* - * A wrapper around the accept() function. The purpose of this wrapper - * is to ensure that the global errno symbol is set if an error occurs, - * even if we are using winsock. - */ -SOCKET -win32_accept(SOCKET fd, struct sockaddr *addr, socklen_t *addr_len) -{ - SOCKET newfd = accept(fd, addr, addr_len); - if (newfd == INVALID_SOCKET) { - set_socket_errno(WSAGetLastError()); - newfd = (SOCKET)-1; - } - return newfd; -} - -/* - * A wrapper around the shutdown() function. The purpose of this wrapper - * is to ensure that the global errno symbol is set if an error occurs, - * even if we are using winsock. - */ -int -win32_shutdown(SOCKET fd, int mode) -{ - int rc = shutdown(fd, mode); - assert(rc == 0 || rc == SOCKET_ERROR); - if (rc == SOCKET_ERROR) { - set_socket_errno(WSAGetLastError()); - } - return rc; -} - -int win32_close_socket(SOCKET fd) -{ - int rc = closesocket(fd); - if (rc == SOCKET_ERROR) { - set_socket_errno(WSAGetLastError()); - } - return rc; -} - -ssize_t win32_write_socket(SOCKET fd, void *buf, int n) -{ - int rc = send(fd, buf, n, 0); - if (rc == SOCKET_ERROR) { - set_socket_errno(WSAGetLastError()); - } - return rc; -} - -ssize_t win32_read_socket(SOCKET fd, void *buf, int n) -{ - int rc = recv(fd, buf, n, 0); - if (rc == SOCKET_ERROR) { - set_socket_errno(WSAGetLastError()); - } - return rc; -} - - -char * win32_strtok_r(char *s, const char *delim, char **lasts) -{ - register char *spanp; - register int c, sc; - char *tok; - - - if (s == NULL && (s = *lasts) == NULL) - return (NULL); - - /* - * Skip (span) leading delimiters (s += strspn(s, delim), sort of). - */ -cont: - c = *s++; - for (spanp = (char *)delim; (sc = *spanp++) != 0;) { - if (c == sc) - goto cont; - } - - if (c == 0) { /* no non-delimiter characters */ - *lasts = NULL; - return (NULL); - } - tok = s - 1; - - /* - * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). - * Note that delim must have one NUL; we stop if we see that, too. - */ - for (;;) { - c = *s++; - spanp = (char *)delim; - do { - if ((sc = *spanp++) == c) { - if (c == 0) - s = NULL; - else - s[-1] = 0; - *lasts = s; - return (tok); - } - } while (sc != 0); - } - /* NOTREACHED */ -} - -char *win32_strsep (char **stringp, const char *delim) -{ - register char *s; - register const char *spanp; - register int c, sc; - char *tok; - - if ((s = *stringp) == NULL) - return (NULL); - for (tok = s;;) { - c = *s++; - spanp = delim; - do { - if ((sc = *spanp++) == c) { - if (c == 0) - s = NULL; - else - s[-1] = 0; - *stringp = s; - return (tok); - } - } while (sc != 0); - } - /* NOTREACHED */ -} - -#ifndef STLINK_HAVE_UNISTD_H -int usleep(unsigned int waitTime) -{ - if (waitTime >= 1000) - { - // Don't do long busy-waits. - // However much it seems like the QPC code would be more accurate, - // you can and probably will lose your time slice at any point during the wait, - // so we might as well voluntarily give up the CPU with a WaitForSingleObject. - HANDLE timer; - LARGE_INTEGER dueTime; - dueTime.QuadPart = -10 * (LONGLONG)waitTime; - - timer = CreateWaitableTimer(NULL, TRUE, NULL); - SetWaitableTimer(timer, &dueTime, 0, NULL, NULL, 0); - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); - return 0; - } - LARGE_INTEGER perf_cnt, start, now; - - QueryPerformanceFrequency(&perf_cnt); - QueryPerformanceCounter(&start); - - do { - QueryPerformanceCounter((LARGE_INTEGER*) &now); - } while ((now.QuadPart - start.QuadPart) / (float)perf_cnt.QuadPart * 1000 * 1000 < waitTime); - - return 0; -} -#endif - -#endif - - diff --git a/src/mmap.h b/src/mmap.h deleted file mode 100644 index ab94fb7d4..000000000 --- a/src/mmap.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef STLINK_MMAP_H -#define STLINK_MMAP_H - -#ifdef STLINK_HAVE_SYS_MMAN_H -#include -#else - -#define PROT_READ (1<<0) -#define PROT_WRITE (1<<1) - -#define MAP_SHARED (1<<0) -#define MAP_PRIVATE (1<<1) - -#define MAP_ANONYMOUS (1<<5) - -#define MAP_FAILED ((void *)-1) - -#ifdef __cplusplus -extern "C" { -#endif - - void *mmap(void *addr, size_t len, int prot, int flags, int fd, long long offset); - int munmap(void *addr, size_t len); - -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_SYS_MMAN_H */ - -#endif /* STLINK_MMAP_H */ diff --git a/src/sg.h b/src/sg.h deleted file mode 100644 index 3a8a7a239..000000000 --- a/src/sg.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * File: sg.h - * Author: karl - * - * Created on October 1, 2011, 11:29 PM - */ - -#ifndef STLINK_SG_H -#define STLINK_SG_H - -#include "libusb_settings.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - - // device access -#define RDWR 0 -#define RO 1 -#define SG_TIMEOUT_SEC 1 // actually 1 is about 2 sec -#define SG_TIMEOUT_MSEC 3 * 1000 - // Each CDB can be a total of 6, 10, 12, or 16 bytes, later version - // of the SCSI standard also allow for variable-length CDBs (min. CDB is 6). - // the stlink needs max. 10 bytes. -#define CDB_6 6 -#define CDB_10 10 -#define CDB_12 12 -#define CDB_16 16 - -#define CDB_SL 10 - - // Query data flow direction. -#define Q_DATA_OUT 0 -#define Q_DATA_IN 1 - - // The SCSI Request Sense command is used to obtain sense data - // (error information) from a target device. - // http://en.wikipedia.org/wiki/SCSI_Request_Sense_Command -#define SENSE_BUF_LEN 32 - - - -struct stlink_libsg { - libusb_context* libusb_ctx; - libusb_device_handle *usb_handle; - unsigned ep_rep; - unsigned ep_req; - - int sg_fd; - int do_scsi_pt_err; - - unsigned char cdb_cmd_blk[CDB_SL]; - - int q_data_dir; // Q_DATA_IN, Q_DATA_OUT - // the start of the query data in the device memory space - uint32_t q_addr; - - // Sense (error information) data - // obsolete, this was fed to the scsi tools - unsigned char sense_buf[SENSE_BUF_LEN]; - - struct stlink_reg reg; -}; - -stlink_t* stlink_v1_open(const int verbose, int reset); - -#ifdef __cplusplus -} -#endif - -#endif /* STLINK_SG_H */ diff --git a/src/tools/flash.c b/src/st-flash/flash.c similarity index 68% rename from src/tools/flash.c rename to src/st-flash/flash.c index 3a83daf8a..43378965c 100644 --- a/src/tools/flash.c +++ b/src/st-flash/flash.c @@ -1,4 +1,4 @@ -/* simple wrapper around the stlink_flash_write function */ +/* Simple wrapper around the stlink_flash_write function */ // TODO - this should be done as just a simple flag to the st-util command line... @@ -9,15 +9,14 @@ #include #include -#include +#include "flash.h" static stlink_t *connected_stlink = NULL; static void cleanup(int signum) { (void)signum; - if (connected_stlink) { - /* Switch back to mass storage mode before closing. */ + if (connected_stlink) { // switch back to mass storage mode before closing stlink_run(connected_stlink); stlink_exit_debug_mode(connected_stlink); stlink_close(connected_stlink); @@ -26,8 +25,7 @@ static void cleanup(int signum) { exit(1); } -static void usage(void) -{ +static void usage(void) { puts("command line: ./st-flash [--debug] [--reset] [--opt] [--serial ] [--format ] [--flash=] [--freq=] {read|write} [addr] [size]"); puts("command line: ./st-flash [--debug] [--freq=] [--serial ] erase"); puts("command line: ./st-flash [--debug] [--freq=] [--serial ] reset"); @@ -39,37 +37,34 @@ static void usage(void) puts("example read option byte: ./st-flash --debug --reset --area=option read > option_byte"); } -int main(int ac, char** av) -{ +int main(int ac, char** av) { stlink_t* sl = NULL; struct flash_opts o; int err = -1; uint8_t * mem = NULL; o.size = 0; - if (flash_get_opts(&o, ac - 1, av + 1) == -1) - { + + if (flash_get_opts(&o, ac - 1, av + 1) == -1) { printf("invalid command line\n"); usage(); - return -1; + return(-1); } printf("st-flash %s\n", STLINK_VERSION); sl = stlink_open_usb(o.log_level, 1, (char *)o.serial, o.freq); - if (sl == NULL) { - return -1; - } + if (sl == NULL) { return(-1); } if (sl->flash_type == STLINK_FLASH_TYPE_UNKNOWN) { printf("Failed to connect to target\n"); - return -1; + return(-1); } if ( o.flash_size != 0u && o.flash_size != sl->flash_size ) { sl->flash_size = o.flash_size; - printf("Forcing flash size: --flash=0x%08X\n",(unsigned int)sl->flash_size); + printf("Forcing flash size: --flash=0x%08X\n", (unsigned int)sl->flash_size); } sl->verbose = o.log_level; @@ -94,7 +89,7 @@ int main(int ac, char** av) } } - if (o.reset){ + if (o.reset) { if (sl->version.stlink_v > 1) { if (stlink_jtag_reset(sl, 2)) { printf("Failed to reset JTAG\n"); @@ -108,19 +103,19 @@ int main(int ac, char** av) } } - // Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 - if (sl->chip_id == STLINK_CHIPID_STM32_F4) - { - memset(sl->q_buf,0,4); - for (int i=0;i<8;i++) { - stlink_write_mem32(sl,0x40026000+0x10+0x18*i,4); - stlink_write_mem32(sl,0x40026400+0x10+0x18*i,4); - stlink_write_mem32(sl,0x40026000+0x24+0x18*i,4); - stlink_write_mem32(sl,0x40026400+0x24+0x18*i,4); + // disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 + if (sl->chip_id == STLINK_CHIPID_STM32_F4) { + memset(sl->q_buf, 0, 4); + + for (int i = 0; i < 8; i++) { + stlink_write_mem32(sl, 0x40026000 + 0x10 + 0x18 * i, 4); + stlink_write_mem32(sl, 0x40026400 + 0x10 + 0x18 * i, 4); + stlink_write_mem32(sl, 0x40026000 + 0x24 + 0x18 * i, 4); + stlink_write_mem32(sl, 0x40026400 + 0x24 + 0x18 * i, 4); } } - // Core must be halted to use RAM based flashloaders + // core must be halted to use RAM based flashloaders if (stlink_force_debug(sl)) { printf("Failed to halt the core\n"); goto on_error; @@ -131,77 +126,75 @@ int main(int ac, char** av) goto on_error; } - if (o.cmd == FLASH_CMD_WRITE) /* write */ - { + if (o.cmd == FLASH_CMD_WRITE) { // write size_t size = 0; + if (o.format == FLASH_FORMAT_IHEX) { err = stlink_parse_ihex(o.filename, stlink_get_erased_pattern(sl), &mem, &size, &o.addr); + if (err == -1) { printf("Cannot parse %s as Intel-HEX file\n", o.filename); goto on_error; } } + if ((o.addr >= sl->flash_base) && - (o.addr < sl->flash_base + sl->flash_size)) { - if (o.format == FLASH_FORMAT_IHEX) + (o.addr < sl->flash_base + sl->flash_size)) { + if (o.format == FLASH_FORMAT_IHEX) { err = stlink_mwrite_flash(sl, mem, (uint32_t)size, o.addr); - else + } else { err = stlink_fwrite_flash(sl, o.filename, o.addr); - if (err == -1) - { + } + + if (err == -1) { printf("stlink_fwrite_flash() == -1\n"); goto on_error; } - } - else if ((o.addr >= sl->sram_base) && - (o.addr < sl->sram_base + sl->sram_size)) { - if (o.format == FLASH_FORMAT_IHEX) + } else if ((o.addr >= sl->sram_base) && + (o.addr < sl->sram_base + sl->sram_size)) { + if (o.format == FLASH_FORMAT_IHEX) { err = stlink_mwrite_sram(sl, mem, (uint32_t)size, o.addr); - else + } else { err = stlink_fwrite_sram(sl, o.filename, o.addr); - if (err == -1) - { + } + + if (err == -1) { printf("stlink_fwrite_sram() == -1\n"); goto on_error; } - } - else if ((o.addr >= sl->option_base) && - (o.addr < sl->option_base + sl->option_size)) { + } else if ((o.addr >= sl->option_base) && + (o.addr < sl->option_base + sl->option_size)) { err = stlink_fwrite_option_bytes(sl, o.filename, o.addr); - if (err == -1) - { + + if (err == -1) { printf("stlink_fwrite_option_bytes() == -1\n"); goto on_error; } - } - else if (o.area == FLASH_OPTION_BYTES){ + } else if (o.area == FLASH_OPTION_BYTES) { if (o.val == 0) { printf("attempting to set option byte to 0, abort.\n"); goto on_error; - } + } err = stlink_write_option_bytes32(sl, o.val); - if (err == -1) - { + + if (err == -1) { printf("stlink_write_option_bytes32() == -1\n"); goto on_error; } - } - else { + } else { err = -1; printf("Unknown memory region\n"); goto on_error; } - } else if (o.cmd == FLASH_CMD_ERASE) - { + } else if (o.cmd == FLASH_CMD_ERASE) { err = stlink_erase_flash_mass(sl); - if (err == -1) - { + + if (err == -1) { printf("stlink_erase_flash_mass() == -1\n"); goto on_error; } - } else if (o.cmd == CMD_RESET) - { + } else if (o.cmd == CMD_RESET) { if (sl->version.stlink_v > 1) { if (stlink_jtag_reset(sl, 2)) { printf("Failed to reset JTAG\n"); @@ -213,49 +206,47 @@ int main(int ac, char** av) printf("Failed to reset device\n"); goto on_error; } - } - else /* read */ - { - if(o.area == FLASH_OPTION_BYTES){ - uint32_t option_byte; - err = stlink_read_option_bytes32(sl, &option_byte); - if (err == -1) { - printf("could not read option bytes (%d)\n", err); - goto on_error; - } else { - printf("%x\n",option_byte); + } else { // read + if (o.area == FLASH_OPTION_BYTES) { + uint32_t option_byte; + err = stlink_read_option_bytes32(sl, &option_byte); + + if (err == -1) { + printf("could not read option bytes (%d)\n", err); + goto on_error; + } else { + printf("%x\n", option_byte); } - }else{ + } else { if ((o.addr >= sl->flash_base) && (o.size == 0) && - (o.addr < sl->flash_base + sl->flash_size)){ + (o.addr < sl->flash_base + sl->flash_size)) { o.size = sl->flash_size; - } - else if ((o.addr >= sl->sram_base) && (o.size == 0) && - (o.addr < sl->sram_base + sl->sram_size)){ + } else if ((o.addr >= sl->sram_base) && (o.size == 0) && + (o.addr < sl->sram_base + sl->sram_size)) { o.size = sl->sram_size; } + err = stlink_fread(sl, o.filename, o.format == FLASH_FORMAT_IHEX, o.addr, o.size); - if (err == -1) - { + if (err == -1) { printf("stlink_fread() == -1\n"); goto on_error; } } } - if (o.reset){ - if (sl->version.stlink_v > 1) stlink_jtag_reset(sl, 2); + if (o.reset) { + if (sl->version.stlink_v > 1) { stlink_jtag_reset(sl, 2); } + stlink_reset(sl); } - /* success */ - err = 0; + err = 0; // success on_error: stlink_exit_debug_mode(sl); stlink_close(sl); free(mem); - return err; + return(err); } diff --git a/include/stlink/tools/flash.h b/src/st-flash/flash.h similarity index 78% rename from include/stlink/tools/flash.h rename to src/st-flash/flash.h index 3a4dc3ec4..0b7555188 100644 --- a/include/stlink/tools/flash.h +++ b/src/st-flash/flash.h @@ -11,9 +11,8 @@ enum flash_cmd {FLASH_CMD_NONE = 0, FLASH_CMD_WRITE = 1, FLASH_CMD_READ = 2, FLASH_CMD_ERASE = 3, CMD_RESET = 4}; enum flash_format {FLASH_FORMAT_BINARY = 0, FLASH_FORMAT_IHEX = 1}; -enum flash_area {FLASH_MAIN_MEMORY = 0, FLASH_SYSTEM_MEMORY = 1,FLASH_OTP = 2, FLASH_OPTION_BYTES = 3}; -struct flash_opts -{ +enum flash_area {FLASH_MAIN_MEMORY = 0, FLASH_SYSTEM_MEMORY = 1, FLASH_OTP = 2, FLASH_OPTION_BYTES = 3}; +struct flash_opts { enum flash_cmd cmd; uint8_t serial[STLINK_SERIAL_MAX_SIZE]; const char* filename; @@ -24,9 +23,9 @@ struct flash_opts enum flash_format format; enum flash_area area; uint32_t val; - size_t flash_size; /* --flash=n[k][m] */ - int opt; /* enable empty tail data drop optimization */ - int freq; /* --freq=n[k][m] frequency of JTAG/SWD */ + size_t flash_size; // --flash=n[k][m] + int opt; // enable empty tail data drop optimization + int freq; // --freq=n[k][m] frequency of JTAG/SWD bool connect_under_reset; }; diff --git a/src/st-flash/flash_opts.c b/src/st-flash/flash_opts.c new file mode 100644 index 000000000..6d1940675 --- /dev/null +++ b/src/st-flash/flash_opts.c @@ -0,0 +1,341 @@ +#include +#include +#include + +#include "flash.h" + +static bool starts_with(const char * str, const char * prefix) { + size_t n = strlen(prefix); + + if (strlen(str) < n) { return(false); } + + return (0 == strncmp(str, prefix, n)); +} + +// support positive integer from 0 to UINT64_MAX +// support decimal, hexadecimal, octal, binary format like 0xff 12 1k 1M, 0b1001 +// negative numbers are not supported +// return 0 if success else return -1 +static int get_long_integer_from_char_array (const char *const str, uint64_t *read_value) { + uint64_t value; + char *tail; + + if (starts_with (str, "0x") || starts_with (str, "0X")) { // hexadecimal + value = strtoul (str + 2, &tail, 16); + } else if (starts_with (str, "0b") || starts_with (str, "0B")) { // binary + value = strtoul (str + 2, &tail, 2); + } else if (starts_with (str, "0")) { // octal + value = strtoul (str + 1, &tail, 8); + } else { // decimal + value = strtoul (str, &tail, 10); + } + + if (((tail[0] == 'k') || (tail[0] == 'K')) && (tail[1] == '\0')) { + value = value * 1024; + } else if (((tail[0] == 'm') || (tail[0] == 'M')) && (tail[1] == '\0')) { + value = value * 1024 * 1024; + } else if (tail[0] == '\0') { + /* value not changed */ + } else { + return(-1); + } + + *read_value = value; + return(0); +} + +// support positive integer from 0 to UINT32_MAX +// support decimal, hexadecimal, octal, binary format like 0xff 12 1k 1M, 0b1001 +// negative numbers are not supported +// return 0 if success else return -1 +static int get_integer_from_char_array (const char *const str, uint32_t *read_value) { + uint64_t value; + int result = get_long_integer_from_char_array (str, &value); + + if (result != 0) { + return(result); + } else if (value > UINT32_MAX) { + fprintf (stderr, "*** Error: Integer greater than UINT32_MAX, cannot convert to int32_t\n"); + return(-1); + } else { + *read_value = (uint32_t)value; + return(0); + } +} + +static int invalid_args(const char *expected) { + fprintf(stderr, "*** Error: Expected args for this command: %s\n", expected); + return(-1); +} + +static int bad_arg(const char *arg) { + fprintf(stderr, "*** Error: Invalid value for %s\n", arg); + return(-1); +} + +int flash_get_opts(struct flash_opts* o, int ac, char** av) { + + // defaults + memset(o, 0, sizeof(*o)); + o->log_level = STND_LOG_LEVEL; + + // options + int result; + + while (ac >= 1) { + if (strcmp(av[0], "--version") == 0) { + printf("v%s\n", STLINK_VERSION); + exit(EXIT_SUCCESS); + } else if (strcmp(av[0], "--debug") == 0) { + o->log_level = DEBUG_LOG_LEVEL; + } else if (strcmp(av[0], "--opt") == 0) { + o->opt = ENABLE_OPT; + } else if (strcmp(av[0], "--reset") == 0) { + o->reset = 1; + } else if (strcmp(av[0], "--serial") == 0 || starts_with(av[0], "--serial=")) { + const char * serial; + + if (strcmp(av[0], "--serial") == 0) { + ac--; + av++; + + if (ac < 1) { return(-1); } + + serial = av[0]; + } else { + serial = av[0] + strlen("--serial="); + } + + /** @todo This is not really portable, as strlen really returns size_t we need to obey + and not cast it to a signed type. */ + int j = (int)strlen(serial); + int length = j / 2; // the length of the destination-array + + if (j % 2 != 0) { return(-1); } + + for (size_t k = 0; j >= 0 && k < sizeof(o->serial); ++k, j -= 2) { + char buffer[3] = {0}; + memcpy(buffer, serial + j, 2); + o->serial[length - k] = (uint8_t)strtol(buffer, NULL, 16); + } + } else if (strcmp(av[0], "--area") == 0 || starts_with(av[0], "--area=")) { + const char * area; + + if (strcmp(av[0], "--area") == 0) { + ac--; + av++; + + if (ac < 1) { return(-1); } + + area = av[0]; + } else { + area = av[0] + strlen("--area="); + } + + if (strcmp(area, "main") == 0) { + o->area = FLASH_MAIN_MEMORY; + } else if (strcmp(area, "system") == 0) { + o->area = FLASH_SYSTEM_MEMORY; + } else if (strcmp(area, "otp") == 0) { + o->area = FLASH_OTP; + } else if (strcmp(area, "option") == 0) { + o->area = FLASH_OPTION_BYTES; + } else { + return(-1); + } + + } else if (strcmp(av[0], "--freq") == 0 || starts_with(av[0], "--freq=")) { + const char* freq; + + if (strcmp(av[0], "--freq") == 0) { + ac--; + av++; + + if (ac < 1) { + return(-1); + } + + freq = av[0]; + } else { + freq = av[0] + strlen("--freq="); + } + + if (strcmp(freq, "5K") == 0 || strcmp(freq, "5k") == 0) { + o->freq = 5; + } else if (strcmp(freq, "15K") == 0 || strcmp(freq, "15k") == 0) { + o->freq = 15; + } else if (strcmp(freq, "25K") == 0 || strcmp(freq, "25k") == 0) { + o->freq = 25; + } else if (strcmp(freq, "50K") == 0 || strcmp(freq, "50k") == 0) { + o->freq = 50; + } else if (strcmp(freq, "100K") == 0 || strcmp(freq, "100k") == 0) { + o->freq = 100; + } else if (strcmp(freq, "125K") == 0 || strcmp(freq, "125k") == 0) { + o->freq = 125; + } else if (strcmp(freq, "240K") == 0 || strcmp(freq, "240k") == 0) { + o->freq = 240; + } else if (strcmp(freq, "480K") == 0 || strcmp(freq, "480k") == 0) { + o->freq = 480; + } else if (strcmp(freq, "950K") == 0 || strcmp(freq, "950k") == 0) { + o->freq = 950; + } else if (strcmp(freq, "1200K") == 0 || strcmp(freq, "1200k") == 0 || + strcmp(freq, "1.2M") == 0 || strcmp(freq, "1.2m") == 0) { + o->freq = 1200; + } else if (strcmp(freq, "1800K") == 0 || strcmp(freq, "1800k") == 0 || + strcmp(freq, "1.8M") == 0 || strcmp(freq, "1.8m") == 0) { + o->freq = 1800; + } else if (strcmp(freq, "4000K") == 0 || strcmp(freq, "4000k") == 0 || + strcmp(freq, "4M") == 0 || strcmp(freq, "4m") == 0) { + o->freq = 4000; + } else { + return(-1); + } + } else if (strcmp(av[0], "--format") == 0 || starts_with(av[0], "--format=")) { + const char * format; + + if (strcmp(av[0], "--format") == 0) { + ac--; + av++; + + if (ac < 1) { return(-1); } + + format = av[0]; + } else { + format = av[0] + strlen("--format="); + } + + if (strcmp(format, "binary") == 0) { + o->format = FLASH_FORMAT_BINARY; + } else if (strcmp(format, "ihex") == 0) { + o->format = FLASH_FORMAT_IHEX; + } else { + return(bad_arg("format")); + } + } else if ( starts_with(av[0], "--flash=")) { + const char *arg = av[0] + strlen("--flash="); + + uint32_t flash_size; + result = get_integer_from_char_array(arg, &flash_size); + + if (result != 0) { + return(bad_arg ("--flash")); + } else { + o->flash_size = (size_t)flash_size; + } + } else if (strcmp(av[0], "--connect-under-reset") == 0) { + o->connect_under_reset = true; + } else { + break; // non-option found + + } + + ac--; + av++; + } + + /* command and (optional) device name */ + while (ac >= 1) { + if (strcmp(av[0], "erase") == 0) { + if (o->cmd != FLASH_CMD_NONE) { return(-1); } + + o->cmd = FLASH_CMD_ERASE; + } else if (strcmp(av[0], "read") == 0) { + if (o->cmd != FLASH_CMD_NONE) { return(-1); } + + o->cmd = FLASH_CMD_READ; + } else if (strcmp(av[0], "write") == 0) { + if (o->cmd != FLASH_CMD_NONE) { return(-1); } + + o->cmd = FLASH_CMD_WRITE; + } else if (strcmp(av[0], "reset") == 0) { + if (o->cmd != FLASH_CMD_NONE) { return(-1); } + + o->cmd = CMD_RESET; + } else { + break; + } + + ac--; + av++; + } + + switch (o->cmd) { + case FLASH_CMD_NONE: // no command found + return(-1); + + case FLASH_CMD_ERASE: // no more arguments expected + + if (ac != 0) { return(-1); } + + break; + + case FLASH_CMD_READ: // expect filename, addr and size + + if ((o->area == FLASH_OPTION_BYTES) && (ac == 0)) { break; } + + if (ac != 3) { return(invalid_args("read ")); } + + if (ac != 3) { return(-1); } + + o->filename = av[0]; + uint32_t address; + result = get_integer_from_char_array(av[1], &address); + + if (result != 0) { + return(bad_arg ("addr")); + } else { + o->addr = (stm32_addr_t)address; + } + + uint32_t size; + result = get_integer_from_char_array(av[2], &size); + + if (result != 0) { + return(bad_arg ("size")); + } else { + o->size = (size_t)size; + } + + break; + + case FLASH_CMD_WRITE: + + if (o->area == FLASH_OPTION_BYTES) { + if (ac != 1) { return(-1); } + + uint32_t val; + result = get_integer_from_char_array(av[0], &val); + + if (result != 0) { + return(bad_arg ("val")); + } else { + o->val = (uint32_t)val; + } + + } else if (o->format == FLASH_FORMAT_BINARY) { // expect filename and addr + if (ac != 2) { return(invalid_args("write ")); } + + o->filename = av[0]; + uint32_t addr; + result = get_integer_from_char_array(av[1], &addr); + + if (result != 0) { + return(bad_arg ("addr")); + } else { + o->addr = (stm32_addr_t)addr; + } + } else if (o->format == FLASH_FORMAT_IHEX) { // expect filename + if (ac != 1) { return(invalid_args("write ")); } + + o->filename = av[0]; + } else { + return(-1); // should have been caught during format parsing + } + + break; + + default: break; + } + + return(0); +} diff --git a/src/tools/info.c b/src/st-info/info.c similarity index 61% rename from src/tools/info.c rename to src/st-info/info.c index 8464d8632..1bc48a05e 100644 --- a/src/tools/info.c +++ b/src/st-info/info.c @@ -5,8 +5,7 @@ #include -static void usage(void) -{ +static void usage(void) { puts("st-info --version"); puts("st-info --probe"); puts("st-info --serial"); @@ -19,31 +18,32 @@ static void usage(void) } /* Print normal or OpenOCD hla_serial with newline */ -static void stlink_print_serial(stlink_t *sl, bool openocd) -{ +static void stlink_print_serial(stlink_t *sl, bool openocd) { const char *fmt; if (openocd) { - printf("\""); - fmt = "\\x%02x"; + printf("\""); + fmt = "\\x%02x"; } else { - fmt = "%02x"; + fmt = "%02x"; } for (int n = 0; n < sl->serial_size; n++) printf(fmt, sl->serial[n]); - if (openocd) - printf("\""); + if (openocd) { + printf("\""); + } + printf("\n"); } -static void stlink_print_info(stlink_t *sl) -{ +static void stlink_print_info(stlink_t *sl) { const struct stlink_chipid_params *params = NULL; - if (!sl) + if (!sl) { return; + } printf(" serial: "); stlink_print_serial(sl, false); @@ -51,18 +51,17 @@ static void stlink_print_info(stlink_t *sl) stlink_print_serial(sl, true); printf(" flash: %u (pagesize: %u)\n", - (unsigned int)sl->flash_size, (unsigned int)sl->flash_pgsz); + (unsigned int)sl->flash_size, (unsigned int)sl->flash_pgsz); printf(" sram: %u\n", (unsigned int)sl->sram_size); printf(" chipid: 0x%.4x\n", sl->chip_id); - params = stlink_chipid_get_params(sl->chip_id); - if (params) - printf(" descr: %s\n", params->description); + params = stlink_chipid_get_params(sl->chip_id); + + if (params) { printf(" descr: %s\n", params->description); } } -static void stlink_probe(void) -{ +static void stlink_probe(void) { stlink_t **stdevs; size_t size; @@ -70,16 +69,15 @@ static void stlink_probe(void) printf("Found %u stlink programmers\n", (unsigned int)size); - for (size_t n = 0; n < size; n++) - stlink_print_info(stdevs[n]); + for (size_t n = 0; n < size; n++) stlink_print_info(stdevs[n]); stlink_probe_usb_free(&stdevs, size); } -static stlink_t *stlink_open_first(bool under_reset) -{ +static stlink_t *stlink_open_first(bool under_reset) { stlink_t* sl = NULL; sl = stlink_v1_open(0, 1); + if (sl == NULL) { if (under_reset) { sl = stlink_open_usb(0, 2, NULL, 0); @@ -87,84 +85,79 @@ static stlink_t *stlink_open_first(bool under_reset) sl = stlink_open_usb(0, 1, NULL, 0); } } - - return sl; + + return(sl); } -static int print_data(int ac, char **av) -{ +static int print_data(int ac, char **av) { stlink_t* sl = NULL; bool under_reset = false; - // Probe needs all devices unclaimed + // probe needs all devices unclaimed if (strcmp(av[1], "--probe") == 0) { stlink_probe(); - return 0; + return(0); } else if (strcmp(av[1], "--version") == 0) { printf("v%s\n", STLINK_VERSION); - return 0; + return(0); } if (ac == 3) { - if (strcmp(av[2],"--connect-under-reset") == 0) { + if (strcmp(av[2], "--connect-under-reset") == 0) { under_reset = true; } else { usage(); - return -1; + return(-1); } } sl = stlink_open_first(under_reset); - if (sl == NULL) { - return -1; - } + if (sl == NULL) { return(-1); } sl->verbose = 0; - if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) - stlink_exit_dfu_mode(sl); + if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { stlink_exit_dfu_mode(sl); } - if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) - stlink_enter_swd_mode(sl); + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } - if (strcmp(av[1], "--serial") == 0) + if (strcmp(av[1], "--serial") == 0) { stlink_print_serial(sl, false); - else if (strcmp(av[1], "--hla-serial") == 0) + } else if (strcmp(av[1], "--hla-serial") == 0) { stlink_print_serial(sl, true); - else if (strcmp(av[1], "--flash") == 0) + } else if (strcmp(av[1], "--flash") == 0) { printf("0x%x\n", (unsigned int)sl->flash_size); - else if (strcmp(av[1], "--pagesize") == 0) + } else if (strcmp(av[1], "--pagesize") == 0) { printf("0x%x\n", (unsigned int)sl->flash_pgsz); - else if (strcmp(av[1], "--sram") == 0) + } else if (strcmp(av[1], "--sram") == 0) { printf("0x%x\n", (unsigned int)sl->sram_size); - else if (strcmp(av[1], "--chipid") == 0) + } else if (strcmp(av[1], "--chipid") == 0) { printf("0x%.4x\n", sl->chip_id); - else if (strcmp(av[1], "--descr") == 0) { + } else if (strcmp(av[1], "--descr") == 0) { const struct stlink_chipid_params *params = stlink_chipid_get_params(sl->chip_id); - if (params == NULL) - return -1; + + if (params == NULL) { return(-1); } + printf("%s\n", params->description); } - if (sl) - { + if (sl) { stlink_exit_debug_mode(sl); stlink_close(sl); } - return 0; + return(0); } -int main(int ac, char** av) -{ +int main(int ac, char** av) { int err = -1; + if (ac < 2) { usage(); - return -1; + return(-1); } - err = print_data(ac,av); + err = print_data(ac, av); - return err; + return(err); } diff --git a/src/st-util/gdb-remote.c b/src/st-util/gdb-remote.c index 24636e8c9..bdf8afd24 100644 --- a/src/st-util/gdb-remote.c +++ b/src/st-util/gdb-remote.c @@ -1,7 +1,6 @@ /* - * Copyright (C) 2011 Peter Zotov - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. + * Copyright (c) 2011 Peter Zotov + * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #include @@ -9,8 +8,8 @@ #include #include -#if defined(__MINGW32__) || defined(_MSC_VER) -#include +#if defined(_WIN32) +#include #else #include #include @@ -21,15 +20,16 @@ static const char hex[] = "0123456789abcdef"; int gdb_send_packet(int fd, char* data) { - unsigned int data_length = (unsigned int) strlen(data); + unsigned int data_length = (unsigned int)strlen(data); int length = data_length + 4; - char* packet = malloc(length); /* '$' data (hex) '#' cksum (hex) */ + char* packet = malloc(length); // '$' data (hex) '#' cksum (hex) memset(packet, 0, length); packet[0] = '$'; uint8_t cksum = 0; + for (unsigned int i = 0; i < data_length; i++) { packet[i + 1] = data[i]; cksum += data[i]; @@ -42,18 +42,19 @@ int gdb_send_packet(int fd, char* data) { while (1) { if (write(fd, packet, length) != length) { free(packet); - return -2; + return(-2); } char ack; + if (read(fd, &ack, 1) != 1) { free(packet); - return -2; + return(-2); } if (ack == '+') { free(packet); - return 0; + return(0); } } } @@ -67,8 +68,9 @@ int gdb_recv_packet(int fd, char** buffer) { char* packet_buffer = malloc(packet_size); unsigned state; - if (packet_buffer == NULL) - return -2; + if (packet_buffer == NULL) { + return(-2); + } start: state = 0; @@ -82,22 +84,25 @@ int gdb_recv_packet(int fd, char** buffer) { */ char c; + while (state != 4) { if (read(fd, &c, 1) != 1) { free(packet_buffer); - return -2; + return(-2); } - switch(state) { + switch (state) { case 0: - if (c != '$') { - // ignore + + if (c != '$') { /* ignore */ } else { state = 1; } + break; case 1: + if (c == '#') { state = 2; } else { @@ -107,14 +112,16 @@ int gdb_recv_packet(int fd, char** buffer) { if (packet_idx == packet_size) { packet_size += ALLOC_STEP; void* p = realloc(packet_buffer, packet_size); - if (p != NULL) + + if (p != NULL) { packet_buffer = p; - else { + } else { free(packet_buffer); - return -2; + return(-2); } } } + break; case 2: @@ -130,31 +137,36 @@ int gdb_recv_packet(int fd, char** buffer) { } uint8_t recv_cksum_int = strtoul(recv_cksum, NULL, 16); + if (recv_cksum_int != cksum) { char nack = '-'; + if (write(fd, &nack, 1) != 1) { free(packet_buffer); - return -2; + return(-2); } goto start; } else { char ack = '+'; + if (write(fd, &ack, 1) != 1) { free(packet_buffer); - return -2; + return(-2); } } packet_buffer[packet_idx] = 0; *buffer = packet_buffer; - return packet_idx; + return(packet_idx); } -// Here we skip any characters which are not \x03, GDB interrupt. -// As we use the mode with ACK, in a (very unlikely) situation of a packet -// lost because of this skipping, it will be resent anyway. +/* + * Here we skip any characters which are not \x03, GDB interrupt. + * As we use the mode with ACK, in a (very unlikely) situation of a packet lost + * because of this skipping, it will be resent anyway. + */ int gdb_check_for_interrupt(int fd) { struct pollfd pfd; pfd.fd = fd; @@ -163,12 +175,14 @@ int gdb_check_for_interrupt(int fd) { if (poll(&pfd, 1, 0) != 0) { char c; - if (read(fd, &c, 1) != 1) - return -2; + if (read(fd, &c, 1) != 1) { + return(-2); + } - if (c == '\x03') // ^C - return 1; + if (c == '\x03') { + return(1); // ^C + } } - return 0; + return(0); } diff --git a/src/st-util/gdb-remote.h b/src/st-util/gdb-remote.h index bfa01046c..6e76746b7 100644 --- a/src/st-util/gdb-remote.h +++ b/src/st-util/gdb-remote.h @@ -5,4 +5,4 @@ int gdb_send_packet(int fd, char* data); int gdb_recv_packet(int fd, char** buffer); int gdb_check_for_interrupt(int fd); -#endif +#endif // _GDB_REMOTE_H_ diff --git a/src/st-util/gdb-server.c b/src/st-util/gdb-server.c index a7107ff88..94cd6fda7 100644 --- a/src/st-util/gdb-server.c +++ b/src/st-util/gdb-server.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2011 Peter Zotov - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. + * Copyright (c) 2011 Peter Zotov + * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ + #include #include #include @@ -10,13 +10,14 @@ #include #include #include + #if defined(_MSC_VER) #include #define __attribute__(x) #endif #if defined(_WIN32) -#include +#include #else #include #include @@ -32,11 +33,11 @@ #define FLASH_BASE 0x08000000 -/* Semihosting doesn't have a short option, we define a value to identify it */ +// Semihosting doesn't have a short option, we define a value to identify it #define SEMIHOSTING_OPTION 128 #define SERIAL_OPTION 127 -//Allways update the FLASH_PAGE before each use, by calling stlink_calculate_pagesize +// always update the FLASH_PAGE before each use, by calling stlink_calculate_pagesize #define FLASH_PAGE (sl->flash_pgsz) static stlink_t *connected_stlink = NULL; @@ -68,13 +69,13 @@ typedef struct _st_state_t { int serve(stlink_t *sl, st_state_t *st); char* make_memory_map(stlink_t *sl); -static void init_cache (stlink_t *sl); +static void init_cache(stlink_t *sl); static void cleanup(int signum) { - (void)signum; + (void)signum; if (connected_stlink) { - /* Switch back to mass storage mode before closing. */ + // Switch back to mass storage mode before closing stlink_run(connected_stlink); stlink_exit_debug_mode(connected_stlink); stlink_close(connected_stlink); @@ -86,12 +87,14 @@ static void cleanup(int signum) { static stlink_t* do_connect(st_state_t *st) { stlink_t *sl = NULL; - if (serial_specified) { - sl = stlink_open_usb(st->logging_level, st->reset, serialnumber, 0); - } else { - sl = stlink_open_usb(st->logging_level, st->reset, NULL, 0); + + if (serial_specified) { + sl = stlink_open_usb(st->logging_level, st->reset, serialnumber, 0); + } else { + sl = stlink_open_usb(st->logging_level, st->reset, NULL, 0); } - return sl; + + return(sl); } @@ -108,92 +111,104 @@ int parse_options(int argc, char** argv, st_state_t *st) { {0, 0, 0, 0}, }; const char * help_str = "%s - usage:\n\n" - " -h, --help\t\tPrint this help\n" - " -V, --version\t\tPrint the version\n" - " -vXX, --verbose=XX\tSpecify a specific verbosity level (0..99)\n" - " -v, --verbose\t\tSpecify generally verbose logging\n" - "\t\t\tChoose what version of stlink to use, (defaults to 2)\n" - " -1, --stlinkv1\tForce stlink version 1\n" - " -p 4242, --listen_port=1234\n" - "\t\t\tSet the gdb server listen port. " - "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n" - " -m, --multi\n" - "\t\t\tSet gdb server to extended mode.\n" - "\t\t\tst-util will continue listening for connections after disconnect.\n" - " -n, --no-reset\n" - "\t\t\tDo not reset board on connection.\n" - " --semihosting\n" - "\t\t\tEnable semihosting support.\n" - " --serial \n" - "\t\t\tUse a specific serial number.\n" - "\n" - "The STLINK device to use can be specified in the environment\n" - "variable STLINK_DEVICE on the format :.\n" - "\n" - ; + " -h, --help\t\tPrint this help\n" + " -V, --version\t\tPrint the version\n" + " -vXX, --verbose=XX\tSpecify a specific verbosity level (0..99)\n" + " -v, --verbose\t\tSpecify generally verbose logging\n" + "\t\t\tChoose what version of stlink to use, (defaults to 2)\n" + " -1, --stlinkv1\tForce stlink version 1\n" + " -p 4242, --listen_port=1234\n" + "\t\t\tSet the gdb server listen port. " + "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n" + " -m, --multi\n" + "\t\t\tSet gdb server to extended mode.\n" + "\t\t\tst-util will continue listening for connections after disconnect.\n" + " -n, --no-reset\n" + "\t\t\tDo not reset board on connection.\n" + " --semihosting\n" + "\t\t\tEnable semihosting support.\n" + " --serial \n" + "\t\t\tUse a specific serial number.\n" + "\n" + "The STLINK device to use can be specified in the environment\n" + "variable STLINK_DEVICE on the format :.\n" + "\n" + ; int option_index = 0; int c; int q; - while ((c = getopt_long(argc, argv, "hv::p:mn", long_options, &option_index)) != -1) { + + while ((c = getopt_long(argc, argv, "hv::p:mn", long_options, &option_index)) != -1) switch (c) { - case 0: - break; - case 'h': - printf(help_str, argv[0]); - exit(EXIT_SUCCESS); - break; - case 'v': - if (optarg) { - st->logging_level = atoi(optarg); - } else { - st->logging_level = DEBUG_LOGGING_LEVEL; - } - break; - case 'p': - sscanf(optarg, "%i", &q); - if (q < 0) { - fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); - exit(EXIT_FAILURE); - } - st->listen_port = q; - break; - case 'm': - st->persistent = 1; - break; - case 'n': - st->reset = 0; - break; - case 'V': - printf("v%s\n", STLINK_VERSION); - exit(EXIT_SUCCESS); - case SEMIHOSTING_OPTION: - semihosting = true; - break; - case SERIAL_OPTION: - printf("use serial %s\n",optarg); - /** @todo This is not really portable, as strlen really returns size_t we need to obey and not cast it to a signed type. */ - int j = (int)strlen(optarg); - int length = j / 2; //the length of the destination-array - if (j % 2 != 0) return -1; - for (size_t k = 0; j >= 0 && k < sizeof(serialnumber); ++k, j -= 2) { - char buffer[3] = {0}; - memcpy(buffer, optarg + j, 2); - serialnumber[length - k] = (uint8_t)strtol(buffer, NULL, 16); - } - serial_specified = true; - break; + case 0: + break; + case 'h': + printf(help_str, argv[0]); + exit(EXIT_SUCCESS); + break; + case 'v': + + if (optarg) { + st->logging_level = atoi(optarg); + } else { + st->logging_level = DEBUG_LOGGING_LEVEL; + } + + break; + case 'p': + sscanf(optarg, "%i", &q); + + if (q < 0) { + fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); + exit(EXIT_FAILURE); + } + + st->listen_port = q; + break; + case 'm': + st->persistent = 1; + break; + case 'n': + st->reset = 0; + break; + case 'V': + printf("v%s\n", STLINK_VERSION); + exit(EXIT_SUCCESS); + case SEMIHOSTING_OPTION: + semihosting = true; + break; + case SERIAL_OPTION: + printf("use serial %s\n", optarg); + /* TODO: This is not really portable, as strlen really returns size_t, + * we need to obey and not cast it to a signed type. + */ + int j = (int)strlen(optarg); + int length = j / 2; // the length of the destination-array + + if (j % 2 != 0) { return(-1); } + + for (size_t k = 0; j >= 0 && k < sizeof(serialnumber); ++k, j -= 2) { + char buffer[3] = {0}; + memcpy(buffer, optarg + j, 2); + serialnumber[length - k] = (uint8_t)strtol(buffer, NULL, 16); + } + + serial_specified = true; + break; } - } + if (optind < argc) { printf("non-option ARGV-elements: "); - while (optind < argc) - printf("%s ", argv[optind++]); + + while (optind < argc) { printf("%s ", argv[optind++]); } + printf("\n"); } - return 0; + + return(0); } int main(int argc, char** argv) { @@ -201,22 +216,21 @@ int main(int argc, char** argv) { st_state_t state; memset(&state, 0, sizeof(state)); - // set defaults... + // set defaults ... state.logging_level = DEFAULT_LOGGING_LEVEL; state.listen_port = DEFAULT_GDB_LISTEN_PORT; - state.reset = 1; /* By default, reset board */ + state.reset = 1; // by default, reset board parse_options(argc, argv, &state); printf("st-util\n"); sl = do_connect(&state); - if (sl == NULL) { - return 1; - } - if (sl->chip_id == STLINK_CHIPID_UNKNOWN) { + if (sl == NULL) { return(1); } + + if (sl->chip_id == STLINK_CHIPID_UNKNOWN) { ELOG("Unsupported Target (Chip ID is %#010x, Core ID is %#010x).\n", sl->chip_id, sl->core_id); - return 1; + return(1); } connected_stlink = sl; @@ -224,46 +238,39 @@ int main(int argc, char** argv) { signal(SIGTERM, &cleanup); signal(SIGSEGV, &cleanup); - if (state.reset) { - stlink_reset(sl); - } + if (state.reset) { stlink_reset(sl); } DLOG("Chip ID is %#010x, Core ID is %#08x.\n", sl->chip_id, sl->core_id); - sl->verbose=0; + sl->verbose = 0; current_memory_map = make_memory_map(sl); -#if defined(__MINGW32__) || defined(_MSC_VER) - WSADATA wsadata; - if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0){ - goto winsock_error; - } +#if defined(_WIN32) + WSADATA wsadata; + + if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) { goto winsock_error; } + #endif init_cache(sl); - do { - if (serve(sl, &state)) { - usleep (1 * 1000); // don't go bezurk if serve returns with error - } - - /* in case serve() changed the connection */ - sl = connected_stlink; + do { // don't go beserk if serve() returns with error + if (serve(sl, &state)) { usleep (1 * 1000); } - /* Continue */ - stlink_run(sl); + sl = connected_stlink; // in case serve() changed the connection + stlink_run(sl); // continue } while (state.persistent); -#if defined(__MINGW32__) || defined(_MSC_VER) +#if defined(_WIN32) winsock_error: WSACleanup(); #endif - /* Switch back to mass storage mode before closing. */ + // switch back to mass storage mode before closing stlink_exit_debug_mode(sl); stlink_close(sl); - return 0; + return(0); } static const char* const target_description_F4 = @@ -339,14 +346,14 @@ static const char* const memory_map_template_F4 = " " // code = sram, bootrom or flash; flash is bigger " " // ccm ram " " // sram - " " //Sectors 0..3 - " 0x4000" //16kB + " " // Sectors 0..3 + " 0x4000" // 16kB " " - " " //Sector 4 - " 0x10000" //64kB + " " // Sector 4 + " 0x10000" // 64kB " " - " " //Sectors 5..11 - " 0x20000" //128kB + " " // Sectors 5..11 + " 0x20000" // 128kB " " " " // peripheral regs " " // AHB3 Peripherals @@ -367,14 +374,14 @@ static const char* const memory_map_template_F4_HD = " " // fmc bank 2 & 3 (nand flash) " " // fmc bank 4 (pc card) " " // fmc sdram bank 1 & 2 - " " //Sectors 0..3 - " 0x4000" //16kB + " " // Sectors 0..3 + " 0x4000" // 16kB " " - " " //Sector 4 - " 0x10000" //64kB + " " // Sector 4 + " 0x10000" // 64kB " " - " " //Sectors 5..11 - " 0x20000" //128kB + " " // Sectors 5..11 + " 0x20000" // 128kB " " " " // peripheral regs " " // cortex regs @@ -387,20 +394,20 @@ static const char* const memory_map_template_F2 = "" "" - " " // code = sram, bootrom or flash; flash is bigger - " " // sram - " " //Sectors 0..3 - " 0x4000" //16kB + " " // code = sram, bootrom or flash; flash is bigger + " " // sram + " " // Sectors 0..3 + " 0x4000" // 16kB " " - " " //Sector 4 - " 0x10000" //64kB + " " // Sector 4 + " 0x10000" // 64kB " " - " " //Sectors 5.. - " 0x20000" //128kB + " " // Sectors 5.. + " 0x20000" // 128kB " " " " // peripheral regs " " // cortex regs - " " // bootrom + " " // bootrom " " // option byte area ""; @@ -409,9 +416,9 @@ static const char* const memory_map_template_L4 = "" "" - " " // code = sram, bootrom or flash; flash is bigger - " " // SRAM2 (32 KB) - " " // SRAM1 (96 KB) + " " // code = sram, bootrom or flash; flash is bigger + " " // SRAM2 (32kB) + " " // SRAM1 (96kB) " " " 0x800" " " @@ -428,9 +435,9 @@ static const char* const memory_map_template_L496 = "" "" - " " // code = sram, bootrom or flash; flash is bigger - " " // SRAM2 (64 KB) - " " // SRAM1 + aliased SRAM2 (256+64=320 KB) + " " // code = sram, bootrom or flash; flash is bigger + " " // SRAM2 (64kB) + " " // SRAM1 + aliased SRAM2 (256 + 64 = 320kB) " " " 0x800" " " @@ -447,14 +454,14 @@ static const char* const memory_map_template = "" "" - " " // code = sram, bootrom or flash; flash is bigger - " " // sram 8k + " " // code = sram, bootrom or flash; flash is bigger + " " // sram 8kB " " " 0x%x" " " " " // peripheral regs " " // cortex regs - " " // bootrom + " " // bootrom " " // option byte area ""; @@ -465,7 +472,7 @@ static const char* const memory_map_template_F7 = "" " " // ITCM ram 16kB " " // ITCM flash - " " // sram + " " // sram " " // Sectors 0..3 " 0x8000" // 32kB " " @@ -490,14 +497,14 @@ static const char* const memory_map_template_F4_DE = "" " " // code = sram, bootrom or flash; flash is bigger " " // sram - " " //Sectors 0..3 - " 0x4000" //16kB + " " // Sectors 0..3 + " 0x4000" // 16kB " " - " " //Sector 4 - " 0x10000" //64kB + " " // Sector 4 + " 0x10000" // 64kB " " - " " //Sectors 5..7 - " 0x20000" //128kB + " " // Sectors 5..7 + " 0x20000" // 128kB " " " " // peripheral regs " " // cortex regs @@ -507,44 +514,51 @@ static const char* const memory_map_template_F4_DE = ""; char* make_memory_map(stlink_t *sl) { - /* This will be freed in serve() */ + // this will be freed in serve() const size_t sz = 4096; char* map = malloc(sz); map[0] = '\0'; - if (sl->chip_id==STLINK_CHIPID_STM32_F4 || sl->chip_id==STLINK_CHIPID_STM32_F446 || sl->chip_id==STLINK_CHIPID_STM32_F411RE) { - strcpy(map, memory_map_template_F4); - } else if (sl->chip_id==STLINK_CHIPID_STM32_F4_DE) { + if (sl->chip_id == STLINK_CHIPID_STM32_F4 || + sl->chip_id == STLINK_CHIPID_STM32_F446 || + sl->chip_id == STLINK_CHIPID_STM32_F411RE) { + strcpy(map, memory_map_template_F4); + } else if (sl->chip_id == STLINK_CHIPID_STM32_F4_DE) { strcpy(map, memory_map_template_F4_DE); - } else if (sl->core_id==STM32F7_CORE_ID) { + } else if (sl->core_id == STM32F7_CORE_ID) { snprintf(map, sz, memory_map_template_F7, - (unsigned int)sl->sram_size); - } else if (sl->chip_id==STLINK_CHIPID_STM32_F4_HD) { + (unsigned int)sl->sram_size); + } else if (sl->chip_id == STLINK_CHIPID_STM32_F4_HD) { strcpy(map, memory_map_template_F4_HD); - } else if (sl->chip_id==STLINK_CHIPID_STM32_F2) { + } else if (sl->chip_id == STLINK_CHIPID_STM32_F2) { snprintf(map, sz, memory_map_template_F2, - (unsigned int)sl->flash_size, - (unsigned int)sl->sram_size, - (unsigned int)sl->flash_size - 0x20000, - (unsigned int)sl->sys_base, (unsigned int)sl->sys_size); - } else if ((sl->chip_id==STLINK_CHIPID_STM32_L4) || - (sl->chip_id==STLINK_CHIPID_STM32_L43X) || - (sl->chip_id==STLINK_CHIPID_STM32_L46X)) { + (unsigned int)sl->flash_size, + (unsigned int)sl->sram_size, + (unsigned int)sl->flash_size - 0x20000, + (unsigned int)sl->sys_base, + (unsigned int)sl->sys_size); + } else if ((sl->chip_id == STLINK_CHIPID_STM32_L4) || + (sl->chip_id == STLINK_CHIPID_STM32_L43X) || + (sl->chip_id == STLINK_CHIPID_STM32_L46X)) { snprintf(map, sz, memory_map_template_L4, - (unsigned int)sl->flash_size, (unsigned int)sl->flash_size); - } else if (sl->chip_id==STLINK_CHIPID_STM32_L496X) { + (unsigned int)sl->flash_size, + (unsigned int)sl->flash_size); + } else if (sl->chip_id == STLINK_CHIPID_STM32_L496X) { snprintf(map, sz, memory_map_template_L496, - (unsigned int)sl->flash_size, (unsigned int)sl->flash_size); + (unsigned int)sl->flash_size, + (unsigned int)sl->flash_size); } else { snprintf(map, sz, memory_map_template, - (unsigned int)sl->flash_size, - (unsigned int)sl->sram_size, - (unsigned int)sl->flash_size, (unsigned int)sl->flash_pgsz, - (unsigned int)sl->sys_base, (unsigned int)sl->sys_size); + (unsigned int)sl->flash_size, + (unsigned int)sl->sram_size, + (unsigned int)sl->flash_size, + (unsigned int)sl->flash_pgsz, + (unsigned int)sl->sys_base, + (unsigned int)sl->sys_size); } - return map; -} + return(map); +} /* * DWT_COMP0 0xE0001020 @@ -578,7 +592,7 @@ static void init_data_watchpoints(stlink_t *sl) { DLOG("init watchpoints\n"); stlink_read_debug32(sl, 0xE000EDFC, &data); - data |= 1<<24; + data |= 1 << 24; // set trcena in debug command to turn on dwt unit stlink_write_debug32(sl, 0xE000EDFC, data); @@ -589,8 +603,7 @@ static void init_data_watchpoints(stlink_t *sl) { } } -static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, - stm32_addr_t addr, unsigned int len) { +static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr, unsigned int len) { int i = 0; uint32_t mask, dummy; @@ -600,13 +613,14 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, mask = -1; i = len; + while (i) { i >>= 1; mask++; } if ((mask != (uint32_t)-1) && (mask < 16)) { - for (i = 0; i < DATA_WATCH_NUM; i++) { + for (i = 0; i < DATA_WATCH_NUM; i++) // is this an empty slot ? if (data_watches[i].fun == WATCHDISABLED) { DLOG("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len); @@ -626,44 +640,42 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, // just to make sure the matched bit is clear ! stlink_read_debug32(sl, 0xE0001028 + i * 16, &dummy); - return 0; + return(0); } - } } DLOG("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len); - return -1; + return(-1); } -static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr) -{ +static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr) { int i; - for (i = 0 ; i < DATA_WATCH_NUM; i++) { + for (i = 0; i < DATA_WATCH_NUM; i++) { if ((data_watches[i].addr == addr) && (data_watches[i].fun != WATCHDISABLED)) { DLOG("delete watchpoint %d addr %x\n", i, addr); data_watches[i].fun = WATCHDISABLED; stlink_write_debug32(sl, 0xe0001028 + i * 16, 0); - return 0; + return(0); } } DLOG("failure: delete watchpoint addr %x\n", addr); - return -1; + return(-1); } static int code_break_num; static int code_lit_num; -#define CODE_BREAK_NUM_MAX 15 -#define CODE_BREAK_LOW 0x01 -#define CODE_BREAK_HIGH 0x02 +#define CODE_BREAK_NUM_MAX 15 +#define CODE_BREAK_LOW 0x01 +#define CODE_BREAK_HIGH 0x02 struct code_hw_breakpoint { stm32_addr_t addr; - int type; + int type; }; static struct code_hw_breakpoint code_breaks[CODE_BREAK_NUM_MAX]; @@ -671,7 +683,7 @@ static struct code_hw_breakpoint code_breaks[CODE_BREAK_NUM_MAX]; static void init_code_breakpoints(stlink_t *sl) { unsigned int val; memset(sl->q_buf, 0, 4); - stlink_write_debug32(sl, STLINK_REG_CM3_FP_CTRL, 0x03 /*KEY | ENABLE4*/); + stlink_write_debug32(sl, STLINK_REG_CM3_FP_CTRL, 0x03 /* KEY | ENABLE4 */); stlink_read_debug32(sl, STLINK_REG_CM3_FP_CTRL, &val); code_break_num = ((val >> 4) & 0xf); code_lit_num = ((val >> 8) & 0xf); @@ -684,14 +696,11 @@ static void init_code_breakpoints(stlink_t *sl) { } } -static int has_breakpoint(stm32_addr_t addr) -{ - for (int i = 0; i < code_break_num; i++) { - if (code_breaks[i].addr == addr) { - return 1; - } - } - return 0; +static int has_breakpoint(stm32_addr_t addr) { + for (int i = 0; i < code_break_num; i++) + if (code_breaks[i].addr == addr) { return(1); } + + return(0); } static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) { @@ -701,65 +710,72 @@ static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) { if (addr & 1) { ELOG("update_code_breakpoint: unaligned address %08x\n", addr); - return -1; + return(-1); } - if (sl->core_id==STM32F7_CORE_ID) { - fpb_addr = addr; - } else { - fpb_addr = addr & ~0x3; - } + if (sl->core_id == STM32F7_CORE_ID) { + fpb_addr = addr; + } else { + fpb_addr = addr & ~0x3; + } int id = -1; - for (int i = 0; i < code_break_num; i++) { - if (fpb_addr == code_breaks[i].addr || - (set && code_breaks[i].type == 0)) { + + for (int i = 0; i < code_break_num; i++) + if (fpb_addr == code_breaks[i].addr || (set && code_breaks[i].type == 0)) { id = i; break; } - } + if (id == -1) { - if (set) return -1; // Free slot not found - else return 0; // Breakpoint is already removed + if (set) { + return(-1); + } // free slot not found + else { + return(0); + } // breakpoint is already removed + } struct code_hw_breakpoint* bp = &code_breaks[id]; bp->addr = fpb_addr; - if (sl->core_id==STM32F7_CORE_ID) { - if (set) bp->type = type; - else bp->type = 0; + if (sl->core_id == STM32F7_CORE_ID) { + if (set) { + bp->type = type; + } else { + bp->type = 0; + } - mask = (bp->addr) | 1; - } else { - if (set) bp->type |= type; - else bp->type &= ~type; + mask = (bp->addr) | 1; + } else { + if (set) { + bp->type |= type; + } else { + bp->type &= ~type; + } - mask = (bp->addr) | 1 | (bp->type << 30); - } + mask = (bp->addr) | 1 | (bp->type << 30); + } if (bp->type == 0) { DLOG("clearing hw break %d\n", id); - stlink_write_debug32(sl, 0xe0002008 + id * 4, 0); } else { - DLOG("setting hw break %d at %08x (%d)\n", - id, bp->addr, bp->type); - DLOG("reg %08x \n", - mask); - + DLOG("setting hw break %d at %08x (%d)\n", id, bp->addr, bp->type); + DLOG("reg %08x \n", mask); stlink_write_debug32(sl, 0xe0002008 + id * 4, mask); } - return 0; + return(0); } struct flash_block { stm32_addr_t addr; - unsigned length; + unsigned length; uint8_t* data; struct flash_block* next; @@ -771,32 +787,32 @@ static int flash_add_block(stm32_addr_t addr, unsigned length, stlink_t *sl) { if (addr < FLASH_BASE || addr + length > FLASH_BASE + sl->flash_size) { ELOG("flash_add_block: incorrect bounds\n"); - return -1; + return(-1); } stlink_calculate_pagesize(sl, addr); + if (addr % FLASH_PAGE != 0 || length % FLASH_PAGE != 0) { ELOG("flash_add_block: unaligned block\n"); - return -1; + return(-1); } struct flash_block* new = malloc(sizeof(struct flash_block)); new->next = flash_root; - new->addr = addr; new->length = length; new->data = calloc(length, 1); flash_root = new; - - return 0; + return(0); } static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) { unsigned int fit_blocks = 0, fit_length = 0; for (struct flash_block* fb = flash_root; fb; fb = fb->next) { - /* Block: ------X------Y-------- + /* + * Block: ------X------Y-------- * Data: a-----b * a--b * a-----------b @@ -806,6 +822,7 @@ static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) { unsigned X = fb->addr, Y = fb->addr + fb->length; unsigned a = addr, b = addr + length; + if (a < Y && b > X) { // from start of the block unsigned start = (a > X ? a : X) - X; @@ -820,22 +837,21 @@ static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) { if (fit_blocks == 0) { ELOG("Unfit data block %08x -> %04x\n", addr, length); - return -1; + return(-1); } if (fit_length != length) { - WLOG("data block %08x -> %04x truncated to %04x\n", - addr, length, fit_length); + WLOG("data block %08x -> %04x truncated to %04x\n", addr, length, fit_length); WLOG("(this is not an error, just a GDB glitch)\n"); } - return 0; + return(0); } static int flash_go(stlink_t *sl) { int error = -1; - // Some kinds of clock settings do not allow writing to flash. + // some kinds of clock settings do not allow writing to flash. stlink_reset(sl); stlink_force_debug(sl); @@ -845,22 +861,22 @@ static int flash_go(stlink_t *sl) { for (stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += (uint32_t)FLASH_PAGE) { unsigned length = fb->length - (page - fb->addr); - //Update FLASH_PAGE + // update FLASH_PAGE stlink_calculate_pagesize(sl, page); DLOG("flash_do: page %08x\n", page); - unsigned len = (length > FLASH_PAGE) ? (unsigned int) FLASH_PAGE : length; + unsigned len = (length > FLASH_PAGE) ? (unsigned int)FLASH_PAGE : length; int ret = stlink_write_flash(sl, page, fb->data + (page - fb->addr), len, 0); - if (ret < 0) - goto error; + + if (ret < 0) { goto error; } } } stlink_reset(sl); - error = 0; error: + for (struct flash_block* fb = flash_root, *next; fb; fb = next) { next = fb->next; free(fb->data); @@ -868,8 +884,7 @@ static int flash_go(stlink_t *sl) { } flash_root = NULL; - - return error; + return(error); } #define CLIDR 0xE000ED78 @@ -882,233 +897,224 @@ static int flash_go(stlink_t *sl) { #define DCCSW 0xE000EF6C #define ICIALLU 0xE000EF50 -struct cache_level_desc -{ - unsigned int nsets; - unsigned int nways; - unsigned int log2_nways; - unsigned int width; +struct cache_level_desc { + unsigned int nsets; + unsigned int nways; + unsigned int log2_nways; + unsigned int width; }; -struct cache_desc_t -{ - /* Minimal line size in bytes. */ - unsigned int dminline; - unsigned int iminline; +struct cache_desc_t { + // minimal line size in bytes + unsigned int dminline; + unsigned int iminline; - /* Last level of unification (uniprocessor). */ - unsigned int louu; + // last level of unification (uniprocessor) + unsigned int louu; - struct cache_level_desc icache[7]; - struct cache_level_desc dcache[7]; + struct cache_level_desc icache[7]; + struct cache_level_desc dcache[7]; }; static struct cache_desc_t cache_desc; -/* Return the smallest R so that V <= (1 << R). Not performance critical. */ -static unsigned ceil_log2(unsigned v) -{ - unsigned res; - for (res = 0; (1U << res) < v; res++) - ; - return res; +// return the smallest R so that V <= (1 << R); not performance critical +static unsigned ceil_log2(unsigned v) { + unsigned res; + + for (res = 0; (1U << res) < v; res++); + + return(res); } -static void read_cache_level_desc(stlink_t *sl, struct cache_level_desc *desc) -{ - unsigned int ccsidr; - unsigned int log2_nsets; - - stlink_read_debug32(sl, CCSIDR, &ccsidr); - desc->nsets = ((ccsidr >> 13) & 0x3fff) + 1; - desc->nways = ((ccsidr >> 3) & 0x1ff) + 1; - desc->log2_nways = ceil_log2 (desc->nways); - log2_nsets = ceil_log2 (desc->nsets); - desc->width = 4 + (ccsidr & 7) + log2_nsets; - ILOG("%08x LineSize: %u, ways: %u, sets: %u (width: %u)\n", - ccsidr, 4 << (ccsidr & 7), desc->nways, desc->nsets, desc->width); +static void read_cache_level_desc(stlink_t *sl, struct cache_level_desc *desc) { + unsigned int ccsidr; + unsigned int log2_nsets; + + stlink_read_debug32(sl, CCSIDR, &ccsidr); + desc->nsets = ((ccsidr >> 13) & 0x3fff) + 1; + desc->nways = ((ccsidr >> 3) & 0x1ff) + 1; + desc->log2_nways = ceil_log2 (desc->nways); + log2_nsets = ceil_log2 (desc->nsets); + desc->width = 4 + (ccsidr & 7) + log2_nsets; + ILOG("%08x LineSize: %u, ways: %u, sets: %u (width: %u)\n", + ccsidr, 4 << (ccsidr & 7), desc->nways, desc->nsets, desc->width); } static void init_cache (stlink_t *sl) { - unsigned int clidr; - unsigned int ccr; - unsigned int ctr; - int i; - - /* Assume only F7 has a cache. */ - if (sl->core_id!=STM32F7_CORE_ID) - return; - - stlink_read_debug32(sl, CLIDR, &clidr); - stlink_read_debug32(sl, CCR, &ccr); - stlink_read_debug32(sl, CTR, &ctr); - cache_desc.dminline = 4 << ((ctr >> 16) & 0x0f); - cache_desc.iminline = 4 << (ctr & 0x0f); - cache_desc.louu = (clidr >> 27) & 7; - - ILOG("Chip clidr: %08x, I-Cache: %s, D-Cache: %s\n", - clidr, ccr & CCR_IC ? "on" : "off", ccr & CCR_DC ? "on" : "off"); - ILOG(" cache: LoUU: %u, LoC: %u, LoUIS: %u\n", - (clidr >> 27) & 7, (clidr >> 24) & 7, (clidr >> 21) & 7); - ILOG(" cache: ctr: %08x, DminLine: %u bytes, IminLine: %u bytes\n", ctr, - cache_desc.dminline, cache_desc.iminline); - for (i = 0; i < 7; i++) - { - unsigned int ct = (clidr >> (3 * i)) & 0x07; - - cache_desc.dcache[i].width = 0; - cache_desc.icache[i].width = 0; - - if (ct == 2 || ct == 3 || ct == 4) - { - /* Data. */ - stlink_write_debug32(sl, CSSELR, i << 1); - ILOG("D-Cache L%d: ", i); - read_cache_level_desc(sl, &cache_desc.dcache[i]); - } - - if (ct == 1 || ct == 3) - { - /* Instruction. */ - stlink_write_debug32(sl, CSSELR, (i << 1) | 1); - ILOG("I-Cache L%d: ", i); - read_cache_level_desc(sl, &cache_desc.icache[i]); - } + unsigned int clidr; + unsigned int ccr; + unsigned int ctr; + int i; + + // assume only F7 has a cache + if (sl->core_id != STM32F7_CORE_ID) { return; } + + stlink_read_debug32(sl, CLIDR, &clidr); + stlink_read_debug32(sl, CCR, &ccr); + stlink_read_debug32(sl, CTR, &ctr); + cache_desc.dminline = 4 << ((ctr >> 16) & 0x0f); + cache_desc.iminline = 4 << (ctr & 0x0f); + cache_desc.louu = (clidr >> 27) & 7; + + ILOG("Chip clidr: %08x, I-Cache: %s, D-Cache: %s\n", + clidr, ccr & CCR_IC ? "on" : "off", ccr & CCR_DC ? "on" : "off"); + ILOG(" cache: LoUU: %u, LoC: %u, LoUIS: %u\n", + (clidr >> 27) & 7, (clidr >> 24) & 7, (clidr >> 21) & 7); + ILOG(" cache: ctr: %08x, DminLine: %u bytes, IminLine: %u bytes\n", ctr, + cache_desc.dminline, cache_desc.iminline); + + for (i = 0; i < 7; i++) { + unsigned int ct = (clidr >> (3 * i)) & 0x07; + cache_desc.dcache[i].width = 0; + cache_desc.icache[i].width = 0; + + if (ct == 2 || ct == 3 || ct == 4) { // data + stlink_write_debug32(sl, CSSELR, i << 1); + ILOG("D-Cache L%d: ", i); + read_cache_level_desc(sl, &cache_desc.dcache[i]); + } + + if (ct == 1 || ct == 3) { // instruction + stlink_write_debug32(sl, CSSELR, (i << 1) | 1); + ILOG("I-Cache L%d: ", i); + read_cache_level_desc(sl, &cache_desc.icache[i]); + } } } static void cache_flush(stlink_t *sl, unsigned ccr) { int level; - if (ccr & CCR_DC) + if (ccr & CCR_DC) { for (level = cache_desc.louu - 1; level >= 0; level--) { struct cache_level_desc *desc = &cache_desc.dcache[level]; unsigned addr; unsigned max_addr = 1 << desc->width; unsigned way_sh = 32 - desc->log2_nways; - /* D-cache clean by set-ways. */ + // D-cache clean by set-ways. for (addr = (level << 1); addr < max_addr; addr += cache_desc.dminline) { unsigned int way; - for (way = 0; way < desc->nways; way++) - stlink_write_debug32(sl, DCCSW, addr | (way << way_sh)); - } + for (way = 0; way < desc->nways; way++) { + stlink_write_debug32(sl, DCCSW, addr | (way << way_sh)); + } + } } + } - /* Invalidate all I-cache to oPU. */ - if (ccr & CCR_IC) + // invalidate all I-cache to oPU + if (ccr & CCR_IC) { stlink_write_debug32(sl, ICIALLU, 0); + } } static int cache_modified; -static void cache_change(stm32_addr_t start, unsigned count) -{ - if (count == 0) - return; - (void)start; - cache_modified = 1; +static void cache_change(stm32_addr_t start, unsigned count) { + if (count == 0) { return; } + + (void)start; + cache_modified = 1; } -static void cache_sync(stlink_t *sl) -{ - unsigned ccr; +static void cache_sync(stlink_t *sl) { + unsigned ccr; + + if (sl->core_id != STM32F7_CORE_ID) { return; } - if (sl->core_id!=STM32F7_CORE_ID) - return; - if (!cache_modified) - return; - cache_modified = 0; + if (!cache_modified) { return; } - stlink_read_debug32(sl, CCR, &ccr); - if (ccr & (CCR_IC | CCR_DC)) - cache_flush(sl, ccr); + cache_modified = 0; + stlink_read_debug32(sl, CCR, &ccr); + + if (ccr & (CCR_IC | CCR_DC)) { cache_flush(sl, ccr); } } -static size_t unhexify(const char *in, char *out, size_t out_count) -{ +static size_t unhexify(const char *in, char *out, size_t out_count) { size_t i; unsigned int c; for (i = 0; i < out_count; i++) { - if (sscanf(in + (2 * i), "%02x", &c) != 1) { - return i; - } + if (sscanf(in + (2 * i), "%02x", &c) != 1) { return(i); } + out[i] = (char)c; } - return i; + return(i); } int serve(stlink_t *sl, st_state_t *st) { SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); + if (!IS_SOCK_VALID(sock)) { perror("socket"); - return 1; + return(1); } unsigned int val = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); struct sockaddr_in serv_addr; - memset(&serv_addr,0,sizeof(struct sockaddr_in)); + memset(&serv_addr, 0, sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(st->listen_port); - if (bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("bind"); close_socket(sock); - return 1; + return(1); } if (listen(sock, 5) < 0) { perror("listen"); close_socket(sock); - return 1; + return(1); } ILOG("Listening at *:%d...\n", st->listen_port); SOCKET client = accept(sock, NULL, NULL); - //signal (SIGINT, SIG_DFL); + + // signal (SIGINT, SIG_DFL); if (!IS_SOCK_VALID(client)) { perror("accept"); close_socket(sock); - return 1; + return(1); } close_socket(sock); stlink_force_debug(sl); - if (st->reset) { - stlink_reset(sl); - } + + if (st->reset) { stlink_reset(sl); } + init_code_breakpoints(sl); init_data_watchpoints(sl); ILOG("GDB connected.\n"); /* - * To allow resetting the chip from GDB it is required to - * emulate attaching and detaching to target. + * To allow resetting the chip from GDB it is required to emulate attaching + * and detaching to target. */ unsigned int attached = 1; - /* - * If a critical error is detected, break from the loop - */ + // if a critical error is detected, break from the loop int critical_error = 0; int ret; + while (1) { ret = 0; char* packet; int status = gdb_recv_packet(client, &packet); + if (status < 0) { ELOG("cannot recv: %d\n", status); close_socket(client); - return 1; + return(1); } DLOG("recv: %s\n", packet); @@ -1116,755 +1122,736 @@ int serve(stlink_t *sl, st_state_t *st) { char* reply = NULL; struct stlink_reg regp; - switch(packet[0]) { - case 'q': { - if (packet[1] == 'P' || packet[1] == 'C' || packet[1] == 'L') { - reply = strdup(""); - break; - } + switch (packet[0]) { + case 'q': { + if (packet[1] == 'P' || packet[1] == 'C' || packet[1] == 'L') { + reply = strdup(""); + break; + } - char *separator = strstr(packet, ":"), *params = ""; - if (separator == NULL) { - separator = packet + strlen(packet); + char *separator = strstr(packet, ":"), *params = ""; + + if (separator == NULL) { + separator = packet + strlen(packet); + } else { + params = separator + 1; + } + + unsigned queryNameLength = (unsigned int)(separator - &packet[1]); + char* queryName = calloc(queryNameLength + 1, 1); + strncpy(queryName, &packet[1], queryNameLength); + + DLOG("query: %s;%s\n", queryName, params); + + if (!strcmp(queryName, "Supported")) { + if (sl->chip_id == STLINK_CHIPID_STM32_F4 || + sl->chip_id == STLINK_CHIPID_STM32_F4_HD || + sl->core_id == STM32F7_CORE_ID) { + reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+"); } else { - params = separator + 1; + reply = strdup("PacketSize=3fff;qXfer:memory-map:read+"); } + } else if (!strcmp(queryName, "Xfer")) { + char *type, *op, *__s_addr, *s_length; + char *tok = params; + char *annex __attribute__((unused)); - unsigned queryNameLength = (unsigned int) (separator - &packet[1]); - char* queryName = calloc(queryNameLength + 1, 1); - strncpy(queryName, &packet[1], queryNameLength); + type = strsep(&tok, ":"); + op = strsep(&tok, ":"); + annex = strsep(&tok, ":"); + __s_addr = strsep(&tok, ","); + s_length = tok; - DLOG("query: %s;%s\n", queryName, params); + unsigned addr = (unsigned int)strtoul(__s_addr, NULL, 16), + length = (unsigned int)strtoul(s_length, NULL, 16); - if (!strcmp(queryName, "Supported")) { - if (sl->chip_id==STLINK_CHIPID_STM32_F4 - || sl->chip_id==STLINK_CHIPID_STM32_F4_HD - || sl->core_id==STM32F7_CORE_ID) { - reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+"); - } - else { - reply = strdup("PacketSize=3fff;qXfer:memory-map:read+"); - } - } else if (!strcmp(queryName, "Xfer")) { - char *type, *op, *__s_addr, *s_length; - char *tok = params; - char *annex __attribute__((unused)); - - type = strsep(&tok, ":"); - op = strsep(&tok, ":"); - annex = strsep(&tok, ":"); - __s_addr = strsep(&tok, ","); - s_length = tok; - - unsigned addr = (unsigned int) strtoul(__s_addr, NULL, 16), - length = (unsigned int) strtoul(s_length, NULL, 16); - - DLOG("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n", - type, op, annex, addr, length); - - const char* data = NULL; - - if (!strcmp(type, "memory-map") && !strcmp(op, "read")) - data = current_memory_map; - - if (!strcmp(type, "features") && !strcmp(op, "read")) - data = target_description_F4; - - if (data) { - unsigned data_length = (unsigned int) strlen(data); - if (addr + length > data_length) - length = data_length - addr; - - if (length == 0) { - reply = strdup("l"); - } else { - reply = calloc(length + 2, 1); - reply[0] = 'm'; - strncpy(&reply[1], data, length); - } - } - } else if (!strncmp(queryName, "Rcmd,",4)) { - // Rcmd uses the wrong separator - separator = strstr(packet, ","); - params = ""; - if (separator == NULL) { - separator = packet + strlen(packet); - } else { - params = separator + 1; - } + DLOG("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n", + type, op, annex, addr, length); - size_t hex_len = strlen(params); - size_t alloc_size = (hex_len / 2) + 1; - size_t cmd_len; - char *cmd = malloc(alloc_size); + const char* data = NULL; - if (cmd == NULL) { - DLOG("Rcmd unhexify allocation error\n"); - break; - } + if (!strcmp(type, "memory-map") && !strcmp(op, "read")) { + data = current_memory_map; + } - cmd_len = unhexify(params, cmd, alloc_size - 1); - cmd[cmd_len] = 0; + if (!strcmp(type, "features") && !strcmp(op, "read")) { + data = target_description_F4; + } - DLOG("unhexified Rcmd: '%s'\n", cmd); + if (data) { + unsigned data_length = (unsigned int)strlen(data); - if (!strncmp(cmd, "resume", 6)) {// resume - DLOG("Rcmd: resume\n"); - cache_sync(sl); - ret = stlink_run(sl); - if (ret) { - DLOG("Rcmd: resume failed\n"); - reply = strdup("E00"); - - } else { - reply = strdup("OK"); - } - - } else if (!strncmp(cmd, "halt", 4)) { //halt - ret = stlink_force_debug(sl); - if (ret) { - DLOG("Rcmd: halt failed\n"); - reply = strdup("E00"); - - } else { - reply = strdup("OK"); - DLOG("Rcmd: halt\n"); - } - - } else if (!strncmp(cmd, "jtag_reset", 10)) { //jtag_reset - reply = strdup("OK"); + if (addr + length > data_length) { length = data_length - addr; } - ret = stlink_jtag_reset(sl, 0); - if (ret) { - DLOG("Rcmd: jtag_reset failed with jtag_reset\n"); - reply = strdup("E00"); - - } - - ret = stlink_jtag_reset(sl, 1); - if (ret) { - DLOG("Rcmd: jtag_reset failed with jtag_reset\n"); - reply = strdup("E00"); - - } - - ret = stlink_force_debug(sl); - if (ret) { - DLOG("Rcmd: jtag_reset failed with force_debug\n"); - reply = strdup("E00"); - - } - if (strcmp(reply, "E00")) { - // no errors have been found - DLOG("Rcmd: jtag_reset\n"); - } - } else if (!strncmp(cmd, "reset", 5)) { //reset - - ret = stlink_force_debug(sl); - if (ret) { - DLOG("Rcmd: reset failed with force_debug\n"); - reply = strdup("E00"); - } - - ret = stlink_reset(sl); - if (ret) { - DLOG("Rcmd: reset failed with reset\n"); - reply = strdup("E00"); - } - - init_code_breakpoints(sl); - init_data_watchpoints(sl); - - if (reply == NULL) { - reply = strdup("OK"); - DLOG("Rcmd: reset\n"); - } - - } else if (!strncmp(cmd, "semihosting ", 12)) { - DLOG("Rcmd: got semihosting cmd '%s'", cmd); - char *arg = cmd + 12; - - /* Skip whitespaces */ - while (isspace(*arg)) { - arg++; - } - - if (!strncmp(arg, "enable", 6) - || !strncmp(arg, "1", 1)) - { - semihosting = true; - reply = strdup("OK"); - } else if (!strncmp(arg, "disable", 7) - || !strncmp(arg, "0", 1)) - { - semihosting = false; - reply = strdup("OK"); - } else { - DLOG("Rcmd: unknown semihosting arg: '%s'\n", arg); - } + if (length == 0) { + reply = strdup("l"); } else { - DLOG("Rcmd: %s\n", cmd); + reply = calloc(length + 2, 1); + reply[0] = 'm'; + strncpy(&reply[1], data, length); } - free(cmd); } + } else if (!strncmp(queryName, "Rcmd,", 4)) { + // Rcmd uses the wrong separator + separator = strstr(packet, ","); + params = ""; - if (reply == NULL) - reply = strdup(""); - - free(queryName); - - break; - } - - case 'v': { - char *params = NULL; - char *cmdName = strtok_r(packet, ":;", ¶ms); + if (separator == NULL) { + separator = packet + strlen(packet); + } else { + params = separator + 1; + } - cmdName++; // vCommand -> Command + size_t hex_len = strlen(params); + size_t alloc_size = (hex_len / 2) + 1; + size_t cmd_len; + char *cmd = malloc(alloc_size); - if (!strcmp(cmdName, "FlashErase")) { - char *__s_addr, *s_length; - char *tok = params; + if (cmd == NULL) { + DLOG("Rcmd unhexify allocation error\n"); + break; + } - __s_addr = strsep(&tok, ","); - s_length = tok; + cmd_len = unhexify(params, cmd, alloc_size - 1); + cmd[cmd_len] = 0; - unsigned addr = (unsigned int) strtoul(__s_addr, NULL, 16), - length = (unsigned int) strtoul(s_length, NULL, 16); + DLOG("unhexified Rcmd: '%s'\n", cmd); - DLOG("FlashErase: addr:%08x,len:%04x\n", - addr, length); + if (!strncmp(cmd, "resume", 6)) { // resume + DLOG("Rcmd: resume\n"); + cache_sync(sl); + ret = stlink_run(sl); - if (flash_add_block(addr, length, sl) < 0) { + if (ret) { + DLOG("Rcmd: resume failed\n"); reply = strdup("E00"); } else { reply = strdup("OK"); } - } else if (!strcmp(cmdName, "FlashWrite")) { - char *__s_addr, *data; - char *tok = params; - - __s_addr = strsep(&tok, ":"); - data = tok; - - unsigned addr = (unsigned int) strtoul(__s_addr, NULL, 16); - unsigned data_length = status - (unsigned int) (data - packet); - - // Length of decoded data cannot be more than - // encoded, as escapes are removed. - // Additional byte is reserved for alignment fix. - uint8_t *decoded = calloc(data_length + 1, 1); - unsigned dec_index = 0; - for (unsigned int i = 0; i < data_length; i++) { - if (data[i] == 0x7d) { - i++; - decoded[dec_index++] = data[i] ^ 0x20; - } else { - decoded[dec_index++] = data[i]; - } - } - // Fix alignment - if (dec_index % 2 != 0) - dec_index++; + } else if (!strncmp(cmd, "halt", 4)) { // halt + ret = stlink_force_debug(sl); - DLOG("binary packet %d -> %d\n", data_length, dec_index); - - if (flash_populate(addr, decoded, dec_index) < 0) { + if (ret) { + DLOG("Rcmd: halt failed\n"); reply = strdup("E00"); } else { reply = strdup("OK"); + DLOG("Rcmd: halt\n"); } - free(decoded); - } else if (!strcmp(cmdName, "FlashDone")) { - if (flash_go(sl) < 0) { + } else if (!strncmp(cmd, "jtag_reset", 10)) { // jtag_reset + reply = strdup("OK"); + ret = stlink_jtag_reset(sl, 0); + + if (ret) { + DLOG("Rcmd: jtag_reset failed with jtag_reset\n"); reply = strdup("E00"); - } else { - reply = strdup("OK"); } - } else if (!strcmp(cmdName, "Kill")) { - attached = 0; - reply = strdup("OK"); - } + ret = stlink_jtag_reset(sl, 1); - if (reply == NULL) - reply = strdup(""); + if (ret) { + DLOG("Rcmd: jtag_reset failed with jtag_reset\n"); + reply = strdup("E00"); + } - break; - } + ret = stlink_force_debug(sl); - case 'c': - cache_sync(sl); - ret = stlink_run(sl); - if (ret) { - DLOG("Semihost: run failed\n"); - } + if (ret) { + DLOG("Rcmd: jtag_reset failed with force_debug\n"); + reply = strdup("E00"); + } - while (1) { - status = gdb_check_for_interrupt(client); - if (status < 0) { - ELOG("cannot check for int: %d\n", status); - close_socket(client); - return 1; + if (strcmp(reply, "E00")) { + // no errors have been found + DLOG("Rcmd: jtag_reset\n"); } + } else if (!strncmp(cmd, "reset", 5)) { // reset - if (status == 1) { - stlink_force_debug(sl); - break; + ret = stlink_force_debug(sl); + + if (ret) { + DLOG("Rcmd: reset failed with force_debug\n"); + reply = strdup("E00"); } - ret = stlink_status(sl); + ret = stlink_reset(sl); + if (ret) { - DLOG("Semihost: status failed\n"); + DLOG("Rcmd: reset failed with reset\n"); + reply = strdup("E00"); } - if(sl->core_stat == TARGET_HALTED) { - struct stlink_reg reg; - stm32_addr_t pc; - stm32_addr_t addr; - int offset = 0; - uint16_t insn; - - if (!semihosting) { - break; - } - - ret = stlink_read_all_regs (sl, ®); - if (ret) { - DLOG("Semihost: read_all_regs failed\n"); - } - - /* Read PC */ - pc = reg.r[15]; - - /* Compute aligned value */ - offset = pc % 4; - addr = pc - offset; - - /* Read instructions (address and length must be - * aligned). - */ - ret = stlink_read_mem32(sl, addr, (offset > 2 ? 8 : 4)); - - if (ret != 0) { - DLOG("Semihost: cannot read instructions at: " - "0x%08x\n", addr); - break; - } - - memcpy(&insn, &sl->q_buf[offset], sizeof(insn)); - - if (insn == 0xBEAB && !has_breakpoint(addr)) { - - ret = do_semihosting (sl, reg.r[0], reg.r[1], ®.r[0]); - if (ret) { - DLOG("Semihost: do_semihosting failed\n"); - } - - /* Write return value */ - ret = stlink_write_reg(sl, reg.r[0], 0); - if (ret) { - DLOG("Semihost: write_reg failed for return value\n"); - } - - /* Jump over the break instruction */ - ret = stlink_write_reg(sl, reg.r[15] + 2, 15); - if (ret) { - DLOG("Semihost: write_reg failed for jumping over break\n"); - } - - /* continue execution */ - cache_sync(sl); - ret = stlink_run(sl); - if (ret) { - DLOG("Semihost: continue execution failed with stlink_run\n"); - } - } else { - break; - } + + init_code_breakpoints(sl); + init_data_watchpoints(sl); + + if (reply == NULL) { + reply = strdup("OK"); + DLOG("Rcmd: reset\n"); } - usleep(100000); - } + } else if (!strncmp(cmd, "semihosting ", 12)) { + DLOG("Rcmd: got semihosting cmd '%s'", cmd); + char *arg = cmd + 12; - reply = strdup("S05"); // TRAP - break; + while (isspace(*arg)) { arg++; } // skip whitespaces - case 's': - cache_sync(sl); - ret = stlink_step(sl); - if (ret) { - // have problem sending step packet - ELOG("Step: cannot send step request\n"); - reply = strdup("E00"); - critical_error = 1; // absolutely critical + if (!strncmp(arg, "enable", 6) || !strncmp(arg, "1", 1)) { + semihosting = true; + reply = strdup("OK"); + } else if (!strncmp(arg, "disable", 7) || !strncmp(arg, "0", 1)) { + semihosting = false; + reply = strdup("OK"); + } else { + DLOG("Rcmd: unknown semihosting arg: '%s'\n", arg); + } } else { - reply = strdup("S05"); // TRAP + DLOG("Rcmd: %s\n", cmd); } - break; + free(cmd); + } + + if (reply == NULL) { reply = strdup(""); } + + free(queryName); + break; + } + + case 'v': { + char *params = NULL; + char *cmdName = strtok_r(packet, ":;", ¶ms); + + cmdName++; // vCommand -> Command + + if (!strcmp(cmdName, "FlashErase")) { + char *__s_addr, *s_length; + char *tok = params; + + __s_addr = strsep(&tok, ","); + s_length = tok; - case '?': - if (attached) { - reply = strdup("S05"); // TRAP + unsigned addr = (unsigned int)strtoul(__s_addr, NULL, 16), + length = (unsigned int)strtoul(s_length, NULL, 16); + + DLOG("FlashErase: addr:%08x,len:%04x\n", + addr, length); + + if (flash_add_block(addr, length, sl) < 0) { + reply = strdup("E00"); } else { - /* Stub shall reply OK if not attached. */ reply = strdup("OK"); } - break; + } else if (!strcmp(cmdName, "FlashWrite")) { + char *__s_addr, *data; + char *tok = params; - case 'g': - ret = stlink_read_all_regs(sl, ®p); - if (ret) { - DLOG("g packet: read_all_regs failed\n"); - } + __s_addr = strsep(&tok, ":"); + data = tok; - reply = calloc(8 * 16 + 1, 1); - for (int i = 0; i < 16; i++) - sprintf(&reply[i * 8], "%08x", (uint32_t)htonl(regp.r[i])); + unsigned addr = (unsigned int)strtoul(__s_addr, NULL, 16); + unsigned data_length = status - (unsigned int)(data - packet); - break; + // Length of decoded data cannot be more than encoded, as escapes are removed. + // Additional byte is reserved for alignment fix. + uint8_t *decoded = calloc(data_length + 1, 1); + unsigned dec_index = 0; - case 'p': { - unsigned id = (unsigned int) strtoul(&packet[1], NULL, 16); - unsigned myreg = 0xDEADDEAD; - - if (id < 16) { - ret = stlink_read_reg(sl, id, ®p); - myreg = htonl(regp.r[id]); - } else if (id == 0x19) { - ret = stlink_read_reg(sl, 16, ®p); - myreg = htonl(regp.xpsr); - } else if (id == 0x1A) { - ret = stlink_read_reg(sl, 17, ®p); - myreg = htonl(regp.main_sp); - } else if (id == 0x1B) { - ret = stlink_read_reg(sl, 18, ®p); - myreg = htonl(regp.process_sp); - } else if (id == 0x1C) { - ret = stlink_read_unsupported_reg(sl, id, ®p); - myreg = htonl(regp.control); - } else if (id == 0x1D) { - ret = stlink_read_unsupported_reg(sl, id, ®p); - myreg = htonl(regp.faultmask); - } else if (id == 0x1E) { - ret = stlink_read_unsupported_reg(sl, id, ®p); - myreg = htonl(regp.basepri); - } else if (id == 0x1F) { - ret = stlink_read_unsupported_reg(sl, id, ®p); - myreg = htonl(regp.primask); - } else if (id >= 0x20 && id < 0x40) { - ret = stlink_read_unsupported_reg(sl, id, ®p); - myreg = htonl(regp.s[id-0x20]); - } else if (id == 0x40) { - ret = stlink_read_unsupported_reg(sl, id, ®p); - myreg = htonl(regp.fpscr); - } else { - ret = 1; - reply = strdup("E00"); - } - if (ret) { - DLOG("p packet: stlink_read_unsupported_reg failed with id %u\n", id); + for (unsigned int i = 0; i < data_length; i++) { + if (data[i] == 0x7d) { + i++; + decoded[dec_index++] = data[i] ^ 0x20; + } else { + decoded[dec_index++] = data[i]; + } } - if (reply == NULL) { - // if reply is set to "E00", skip - reply = calloc(8 + 1, 1); - sprintf(reply, "%08x", myreg); - } + // fix alignment + if (dec_index % 2 != 0) { dec_index++; } - break; - } + DLOG("binary packet %d -> %d\n", data_length, dec_index); - case 'P': { - char* s_reg = &packet[1]; - char* s_value = strstr(&packet[1], "=") + 1; - - unsigned reg = (unsigned int) strtoul(s_reg, NULL, 16); - unsigned value = (unsigned int) strtoul(s_value, NULL, 16); - - - if (reg < 16) { - ret = stlink_write_reg(sl, ntohl(value), reg); - } else if (reg == 0x19) { - ret = stlink_write_reg(sl, ntohl(value), 16); - } else if (reg == 0x1A) { - ret = stlink_write_reg(sl, ntohl(value), 17); - } else if (reg == 0x1B) { - ret = stlink_write_reg(sl, ntohl(value), 18); - } else if (reg == 0x1C) { - ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); - } else if (reg == 0x1D) { - ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); - } else if (reg == 0x1E) { - ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); - } else if (reg == 0x1F) { - ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); - } else if (reg >= 0x20 && reg < 0x40) { - ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); - } else if (reg == 0x40) { - ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); - } else { - ret = 1; + if (flash_populate(addr, decoded, dec_index) < 0) { reply = strdup("E00"); - } - if (ret) { - DLOG("P packet: stlink_write_unsupported_reg failed with reg %u\n", reg); - } - if (reply == NULL) { - // note that NULL may not be zero + } else { reply = strdup("OK"); } - break; + free(decoded); + } else if (!strcmp(cmdName, "FlashDone")) { + if (flash_go(sl) < 0) { + reply = strdup("E00"); + } else { + reply = strdup("OK"); + } + } else if (!strcmp(cmdName, "Kill")) { + attached = 0; + reply = strdup("OK"); } - case 'G': - for (int i = 0; i < 16; i++) { - char str[9] = {0}; - strncpy(str, &packet[1 + i * 8], 8); - uint32_t reg = (uint32_t) strtoul(str, NULL, 16); - ret = stlink_write_reg(sl, ntohl(reg), i); - if (ret) { - DLOG("G packet: stlink_write_reg failed"); - } - } + if (reply == NULL) { reply = strdup(""); } - reply = strdup("OK"); - break; + break; + } - case 'm': { - char* s_start = &packet[1]; - char* s_count = strstr(&packet[1], ",") + 1; - - stm32_addr_t start = (stm32_addr_t) strtoul(s_start, NULL, 16); - unsigned count = (unsigned int) strtoul(s_count, NULL, 16); - - unsigned adj_start = start % 4; - unsigned count_rnd = (count + adj_start + 4 - 1) / 4 * 4; - if (count_rnd > sl->flash_pgsz) - count_rnd = (unsigned int) sl->flash_pgsz; - if (count_rnd > 0x1800) - count_rnd = 0x1800; - if (count_rnd < count) - count = count_rnd; - - if (stlink_read_mem32(sl, start - adj_start, count_rnd) != 0) { - /* read failed somehow, don't return stale buffer */ - count = 0; + case 'c': + cache_sync(sl); + ret = stlink_run(sl); + + if (ret) { DLOG("Semihost: run failed\n"); } + + while (1) { + status = gdb_check_for_interrupt(client); + + if (status < 0) { + ELOG("cannot check for int: %d\n", status); + close_socket(client); + return(1); } - reply = calloc(count * 2 + 1, 1); - for (unsigned int i = 0; i < count; i++) { - reply[i * 2 + 0] = hex[sl->q_buf[i + adj_start] >> 4]; - reply[i * 2 + 1] = hex[sl->q_buf[i + adj_start] & 0xf]; + if (status == 1) { + stlink_force_debug(sl); + break; } - break; - } + ret = stlink_status(sl); - case 'M': { - char* s_start = &packet[1]; - char* s_count = strstr(&packet[1], ",") + 1; - char* hexdata = strstr(packet, ":") + 1; - - stm32_addr_t start = (stm32_addr_t) strtoul(s_start, NULL, 16); - unsigned count = (unsigned int) strtoul(s_count, NULL, 16); - int err = 0; - - if (start % 4) { - unsigned align_count = 4 - start % 4; - if (align_count > count) align_count = count; - for (unsigned int i = 0; i < align_count; i ++) { - char hextmp[3] = { hexdata[i*2], hexdata[i*2+1], 0 }; - uint8_t byte = strtoul(hextmp, NULL, 16); - sl->q_buf[i] = byte; - } - err |= stlink_write_mem8(sl, start, align_count); - cache_change(start, align_count); - start += align_count; - count -= align_count; - hexdata += 2*align_count; - } + if (ret) { DLOG("Semihost: status failed\n"); } + + if (sl->core_stat == TARGET_HALTED) { + struct stlink_reg reg; + stm32_addr_t pc; + stm32_addr_t addr; + int offset = 0; + uint16_t insn; + + if (!semihosting) { break; } + + ret = stlink_read_all_regs (sl, ®); - if (count - count % 4) { - unsigned aligned_count = count - count % 4; + if (ret) { DLOG("Semihost: read_all_regs failed\n"); } - for (unsigned int i = 0; i < aligned_count; i ++) { - char hextmp[3] = { hexdata[i*2], hexdata[i*2+1], 0 }; - uint8_t byte = strtoul(hextmp, NULL, 16); - sl->q_buf[i] = byte; + // read PC + pc = reg.r[15]; + + // compute aligned value + offset = pc % 4; + addr = pc - offset; + + // read instructions (address and length must be aligned). + ret = stlink_read_mem32(sl, addr, (offset > 2 ? 8 : 4)); + + if (ret != 0) { + DLOG("Semihost: cannot read instructions at: 0x%08x\n", addr); + break; } - err |= stlink_write_mem32(sl, start, aligned_count); - cache_change(start, aligned_count); - count -= aligned_count; - start += aligned_count; - hexdata += 2*aligned_count; - } - if (count) { - for (unsigned int i = 0; i < count; i ++) { - char hextmp[3] = { hexdata[i*2], hexdata[i*2+1], 0 }; - uint8_t byte = strtoul(hextmp, NULL, 16); - sl->q_buf[i] = byte; + memcpy(&insn, &sl->q_buf[offset], sizeof(insn)); + + if (insn == 0xBEAB && !has_breakpoint(addr)) { + + ret = do_semihosting (sl, reg.r[0], reg.r[1], ®.r[0]); + + if (ret) { DLOG("Semihost: do_semihosting failed\n"); } + + // write return value + ret = stlink_write_reg(sl, reg.r[0], 0); + + if (ret) { DLOG("Semihost: write_reg failed for return value\n"); } + + // jump over the break instruction + ret = stlink_write_reg(sl, reg.r[15] + 2, 15); + + if (ret) { DLOG("Semihost: write_reg failed for jumping over break\n"); } + + // continue execution + cache_sync(sl); + ret = stlink_run(sl); + + if (ret) { DLOG("Semihost: continue execution failed with stlink_run\n"); } + } else { + break; } - err |= stlink_write_mem8(sl, start, count); - cache_change(start, count); } - reply = strdup(err ? "E00" : "OK"); - break; + + usleep(100000); } - case 'Z': { - char *endptr; - stm32_addr_t addr = (stm32_addr_t) strtoul(&packet[3], &endptr, 16); - stm32_addr_t len = (stm32_addr_t) strtoul(&endptr[1], NULL, 16); - - switch (packet[1]) { - case '1': - if (update_code_breakpoint(sl, addr, 1) < 0) { - reply = strdup("E00"); - } else { - reply = strdup("OK"); - } - break; + reply = strdup("S05"); // TRAP + break; - case '2': // insert write watchpoint - case '3': // insert read watchpoint - case '4': { // insert access watchpoint - enum watchfun wf; - if (packet[1] == '2') { - wf = WATCHWRITE; - } else if (packet[1] == '3') { - wf = WATCHREAD; - } else { - wf = WATCHACCESS; - } - - if (add_data_watchpoint(sl, wf, addr, len) < 0) { - reply = strdup("E00"); - } else { - reply = strdup("OK"); - break; - } - } - break; + case 's': + cache_sync(sl); + ret = stlink_step(sl); - default: - reply = strdup(""); - } - break; + if (ret) { + // ... having a problem sending step packet + ELOG("Step: cannot send step request\n"); + reply = strdup("E00"); + critical_error = 1; // absolutely critical + } else { + reply = strdup("S05"); // TRAP } - case 'z': { - char *endptr; - stm32_addr_t addr = (stm32_addr_t) strtoul(&packet[3], &endptr, 16); - //stm32_addr_t len = strtoul(&endptr[1], NULL, 16); - - switch (packet[1]) { - case '1': // remove breakpoint - update_code_breakpoint(sl, addr, 0); - reply = strdup("OK"); - break; - case '2' : // remove write watchpoint - case '3' : // remove read watchpoint - case '4' : // remove access watchpoint - if (delete_data_watchpoint(sl, addr) < 0) { - reply = strdup("E00"); - break; - } else { - reply = strdup("OK"); - break; - } - - default: - reply = strdup(""); - } - break; + break; + + case '?': + + if (attached) { + reply = strdup("S05"); // TRAP + } else { + reply = strdup("OK"); // stub shall reply OK if not attached } - case '!': { - /* - * Enter extended mode which allows restarting. - * We do support that always. - */ + break; + + case 'g': + ret = stlink_read_all_regs(sl, ®p); - /* - * Also, set to persistent mode - * to allow GDB disconnect. - */ - st->persistent = 1; + if (ret) { DLOG("g packet: read_all_regs failed\n"); } - reply = strdup("OK"); + reply = calloc(8 * 16 + 1, 1); - break; + for (int i = 0; i < 16; i++) { + sprintf(&reply[i * 8], "%08x", (uint32_t)htonl(regp.r[i])); } - case 'R': { + break; - /* Reset the core. */ + case 'p': { + unsigned id = (unsigned int)strtoul(&packet[1], NULL, 16); + unsigned myreg = 0xDEADDEAD; + + if (id < 16) { + ret = stlink_read_reg(sl, id, ®p); + myreg = htonl(regp.r[id]); + } else if (id == 0x19) { + ret = stlink_read_reg(sl, 16, ®p); + myreg = htonl(regp.xpsr); + } else if (id == 0x1A) { + ret = stlink_read_reg(sl, 17, ®p); + myreg = htonl(regp.main_sp); + } else if (id == 0x1B) { + ret = stlink_read_reg(sl, 18, ®p); + myreg = htonl(regp.process_sp); + } else if (id == 0x1C) { + ret = stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.control); + } else if (id == 0x1D) { + ret = stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.faultmask); + } else if (id == 0x1E) { + ret = stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.basepri); + } else if (id == 0x1F) { + ret = stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.primask); + } else if (id >= 0x20 && id < 0x40) { + ret = stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.s[id - 0x20]); + } else if (id == 0x40) { + ret = stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.fpscr); + } else { + ret = 1; + reply = strdup("E00"); + } - ret = stlink_reset(sl); - if (ret) { - DLOG("R packet : stlink_reset failed\n"); - } - init_code_breakpoints(sl); - init_data_watchpoints(sl); + if (ret) { DLOG("p packet: stlink_read_unsupported_reg failed with id %u\n", id); } - attached = 1; + if (reply == NULL) { + // if reply is set to "E00", skip + reply = calloc(8 + 1, 1); + sprintf(reply, "%08x", myreg); + } - reply = strdup("OK"); + break; + } - break; + case 'P': { + char* s_reg = &packet[1]; + char* s_value = strstr(&packet[1], "=") + 1; + + unsigned reg = (unsigned int)strtoul(s_reg, NULL, 16); + unsigned value = (unsigned int)strtoul(s_value, NULL, 16); + + + if (reg < 16) { + ret = stlink_write_reg(sl, ntohl(value), reg); + } else if (reg == 0x19) { + ret = stlink_write_reg(sl, ntohl(value), 16); + } else if (reg == 0x1A) { + ret = stlink_write_reg(sl, ntohl(value), 17); + } else if (reg == 0x1B) { + ret = stlink_write_reg(sl, ntohl(value), 18); + } else if (reg == 0x1C) { + ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if (reg == 0x1D) { + ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if (reg == 0x1E) { + ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if (reg == 0x1F) { + ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if (reg >= 0x20 && reg < 0x40) { + ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if (reg == 0x40) { + ret = stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else { + ret = 1; + reply = strdup("E00"); } - case 'k': - /* Kill request - reset the connection itself */ - ret = stlink_run(sl); - if (ret) { - DLOG("Kill: stlink_run failed\n"); + + if (ret) { DLOG("P packet: stlink_write_unsupported_reg failed with reg %u\n", reg); } + + if (reply == NULL) { reply = strdup("OK"); /* Note: NULL may not be zero */ } + + break; + } + + case 'G': + + for (int i = 0; i < 16; i++) { + char str[9] = {0}; + strncpy(str, &packet[1 + i * 8], 8); + uint32_t reg = (uint32_t)strtoul(str, NULL, 16); + ret = stlink_write_reg(sl, ntohl(reg), i); + + if (ret) { DLOG("G packet: stlink_write_reg failed"); } + } + + reply = strdup("OK"); + break; + + case 'm': { + char* s_start = &packet[1]; + char* s_count = strstr(&packet[1], ",") + 1; + + stm32_addr_t start = (stm32_addr_t)strtoul(s_start, NULL, 16); + unsigned count = (unsigned int)strtoul(s_count, NULL, 16); + + unsigned adj_start = start % 4; + unsigned count_rnd = (count + adj_start + 4 - 1) / 4 * 4; + + if (count_rnd > sl->flash_pgsz) { count_rnd = (unsigned int)sl->flash_pgsz; } + + if (count_rnd > 0x1800) { count_rnd = 0x1800; } + + if (count_rnd < count) { count = count_rnd; } + + if (stlink_read_mem32(sl, start - adj_start, count_rnd) != 0) { count = 0; } + + // read failed somehow, don't return stale buffer + + reply = calloc(count * 2 + 1, 1); + + for (unsigned int i = 0; i < count; i++) { + reply[i * 2 + 0] = hex[sl->q_buf[i + adj_start] >> 4]; + reply[i * 2 + 1] = hex[sl->q_buf[i + adj_start] & 0xf]; + } + + break; + } + + case 'M': { + char* s_start = &packet[1]; + char* s_count = strstr(&packet[1], ",") + 1; + char* hexdata = strstr(packet, ":") + 1; + + stm32_addr_t start = (stm32_addr_t)strtoul(s_start, NULL, 16); + unsigned count = (unsigned int)strtoul(s_count, NULL, 16); + int err = 0; + + if (start % 4) { + unsigned align_count = 4 - start % 4; + + if (align_count > count) { align_count = count; } + + for (unsigned int i = 0; i < align_count; i++) { + char hextmp[3] = { hexdata[i * 2], hexdata[i * 2 + 1], 0 }; + uint8_t byte = strtoul(hextmp, NULL, 16); + sl->q_buf[i] = byte; + } + + err |= stlink_write_mem8(sl, start, align_count); + cache_change(start, align_count); + start += align_count; + count -= align_count; + hexdata += 2 * align_count; + } + + if (count - count % 4) { + unsigned aligned_count = count - count % 4; + + for (unsigned int i = 0; i < aligned_count; i++) { + char hextmp[3] = { hexdata[i * 2], hexdata[i * 2 + 1], 0 }; + uint8_t byte = strtoul(hextmp, NULL, 16); + sl->q_buf[i] = byte; } - ret = stlink_exit_debug_mode(sl); - if (ret) { - DLOG("Kill: stlink_exit_debug_mode failed\n"); + err |= stlink_write_mem32(sl, start, aligned_count); + cache_change(start, aligned_count); + count -= aligned_count; + start += aligned_count; + hexdata += 2 * aligned_count; + } + + if (count) { + for (unsigned int i = 0; i < count; i++) { + char hextmp[3] = { hexdata[i * 2], hexdata[i * 2 + 1], 0 }; + uint8_t byte = strtoul(hextmp, NULL, 16); + sl->q_buf[i] = byte; } - stlink_close(sl); - sl = do_connect(st); - if (sl == NULL || sl->chip_id == STLINK_CHIPID_UNKNOWN) - cleanup(0); - connected_stlink = sl; + err |= stlink_write_mem8(sl, start, count); + cache_change(start, count); + } + + reply = strdup(err ? "E00" : "OK"); + break; + } + + case 'Z': { + char *endptr; + stm32_addr_t addr = (stm32_addr_t)strtoul(&packet[3], &endptr, 16); + stm32_addr_t len = (stm32_addr_t)strtoul(&endptr[1], NULL, 16); - if (st->reset) { - stlink_reset(sl); + switch (packet[1]) { + case '1': + + if (update_code_breakpoint(sl, addr, 1) < 0) { + reply = strdup("E00"); + } else { + reply = strdup("OK"); } - ret = stlink_force_debug(sl); - if (ret) { - DLOG("Kill: stlink_force_debug failed\n"); + + break; + + case '2': // insert write watchpoint + case '3': // insert read watchpoint + case '4': { // insert access watchpoint + enum watchfun wf; + + if (packet[1] == '2') { + wf = WATCHWRITE; + } else if (packet[1] == '3') { + wf = WATCHREAD; + } else { + wf = WATCHACCESS; } - init_cache(sl); - init_code_breakpoints(sl); - init_data_watchpoints(sl); - reply = NULL; /* no response */ + if (add_data_watchpoint(sl, wf, addr, len) < 0) { + reply = strdup("E00"); + } else { + reply = strdup("OK"); + break; + } + } + break; + default: + reply = strdup(""); + } + break; + } + case 'z': { + char *endptr; + stm32_addr_t addr = (stm32_addr_t)strtoul(&packet[3], &endptr, 16); + // stm32_addr_t len = strtoul(&endptr[1], NULL, 16); + + switch (packet[1]) { + case '1': // remove breakpoint + update_code_breakpoint(sl, addr, 0); + reply = strdup("OK"); break; + case '2': // remove write watchpoint + case '3': // remove read watchpoint + case '4': // remove access watchpoint + + if (delete_data_watchpoint(sl, addr) < 0) { + reply = strdup("E00"); + break; + } else { + reply = strdup("OK"); + break; + } + default: reply = strdup(""); + } + break; + } + + case '!': { + // enter extended mode which allows restarting. We do support that always. + // also, set to persistent mode to allow GDB disconnect. + st->persistent = 1; + + reply = strdup("OK"); + break; + } + + case 'R': { + // reset the core. + ret = stlink_reset(sl); + + if (ret) { DLOG("R packet : stlink_reset failed\n"); } + + init_code_breakpoints(sl); + init_data_watchpoints(sl); + + attached = 1; + + reply = strdup("OK"); + break; + } + case 'k': + // kill request - reset the connection itself + ret = stlink_run(sl); + + if (ret) { DLOG("Kill: stlink_run failed\n"); } + + ret = stlink_exit_debug_mode(sl); + + if (ret) { DLOG("Kill: stlink_exit_debug_mode failed\n"); } + + stlink_close(sl); + + sl = do_connect(st); + + if (sl == NULL || sl->chip_id == STLINK_CHIPID_UNKNOWN) { cleanup(0); } + + connected_stlink = sl; + + if (st->reset) { stlink_reset(sl); } + + ret = stlink_force_debug(sl); + + if (ret) { DLOG("Kill: stlink_force_debug failed\n"); } + + init_cache(sl); + init_code_breakpoints(sl); + init_data_watchpoints(sl); + + reply = NULL; // no response + break; + + default: + reply = strdup(""); } if (reply) { DLOG("send: %s\n", reply); int result = gdb_send_packet(client, reply); + if (result != 0) { ELOG("cannot send: %d\n", result); free(reply); free(packet); close_socket(client); - return 1; + return(1); } free(reply); @@ -1872,13 +1859,12 @@ int serve(stlink_t *sl, st_state_t *st) { if (critical_error) { close_socket(client); - return 1; + return(1); } free(packet); } close_socket(client); - - return 0; + return(0); } diff --git a/src/st-util/gdb-server.h b/src/st-util/gdb-server.h index 8c8d47114..b50a7941d 100644 --- a/src/st-util/gdb-server.h +++ b/src/st-util/gdb-server.h @@ -8,4 +8,4 @@ #define DEBUG_LOGGING_LEVEL 100 #define DEFAULT_GDB_LISTEN_PORT 4242 -#endif +#endif // _GDB_SERVER_H diff --git a/src/st-util/semihosting.c b/src/st-util/semihosting.c index fed66ab60..821dcdbbb 100644 --- a/src/st-util/semihosting.c +++ b/src/st-util/semihosting.c @@ -9,120 +9,87 @@ #include #include "semihosting.h" -static int mem_read_u8(stlink_t *sl, uint32_t addr, uint8_t *data) -{ +static int mem_read_u8(stlink_t *sl, uint32_t addr, uint8_t *data) { int offset = addr % 4; int len = 4; - if (sl == NULL || data == NULL) { - return -1; - } + if (sl == NULL || data == NULL) { return(-1); } - /* Read address and length must be aligned */ - if (stlink_read_mem32(sl, addr - offset, len) != 0) { - return -1; - } + // read address and length must be aligned + if (stlink_read_mem32(sl, addr - offset, len) != 0) { return(-1); } *data = sl->q_buf[offset]; - return 0; + return(0); } #ifdef UNUSED -static int mem_read_u16(stlink_t *sl, uint32_t addr, uint16_t *data) -{ +static int mem_read_u16(stlink_t *sl, uint32_t addr, uint16_t *data) { int offset = addr % 4; int len = (offset > 2 ? 8 : 4); - if (sl == NULL || data == NULL) { - return -1; - } + if (sl == NULL || data == NULL) { return(-1); } - /* Read address and length must be aligned */ - if (stlink_read_mem32(sl, addr - offset, len) != 0) { - return -1; - } + // read address and length must be aligned + if (stlink_read_mem32(sl, addr - offset, len) != 0) { return(-1); } memcpy(data, &sl->q_buf[offset], sizeof(*data)); - return 0; + return(0); } -static int mem_read_u32(stlink_t *sl, uint32_t addr, uint32_t *data) -{ +static int mem_read_u32(stlink_t *sl, uint32_t addr, uint32_t *data) { int offset = addr % 4; int len = (offset > 0 ? 8 : 4); - if (sl == NULL || data == NULL) { - return -1; - } + if (sl == NULL || data == NULL) { return(-1); } - /* Read address and length must be aligned */ - if (stlink_read_mem32(sl, addr - offset, len) != 0) { - return -1; - } + // read address and length must be aligned + if (stlink_read_mem32(sl, addr - offset, len) != 0) { return(-1); } memcpy(data, &sl->q_buf[offset], sizeof(*data)); - return 0; + return(0); } #endif -static int mem_read(stlink_t *sl, uint32_t addr, void *data, uint16_t len) -{ +static int mem_read(stlink_t *sl, uint32_t addr, void *data, uint16_t len) { int offset = addr % 4; int read_len = len + offset; - if (sl == NULL || data == NULL) { - return -1; - } + if (sl == NULL || data == NULL) { return(-1); } - /* Align read size */ - if ((read_len % 4) != 0) { - read_len += 4 - (read_len % 4); - } + // align read size + if ((read_len % 4) != 0) { read_len += 4 - (read_len % 4); } - /* Address and length must be aligned */ - if (stlink_read_mem32(sl, addr - offset, read_len) != 0) { - return -1; - } + // address and length must be aligned + if (stlink_read_mem32(sl, addr - offset, read_len) != 0) { return(-1); } memcpy(data, &sl->q_buf[offset], len); - return 0; + return(0); } -static int mem_write(stlink_t *sl, uint32_t addr, void *data, uint16_t len) -{ - // Note: this function can write more than it is asked to! - // If addr is not an even 32 bit boundary, or len is not a multiple of 4. - // - // If only 32 bit values can be written to the target, - // then this function should read the target memory at the - // start and end of the buffer where it will write more that - // the requested bytes. (perhaps reading the whole area is faster??). - // - // If 16 and 8 bit writes are available, then they could be used instead. - - // Just return when the length is zero avoiding unneeded work. - if (len == 0) return 0; +static int mem_write(stlink_t *sl, uint32_t addr, void *data, uint16_t len) { + /* Note: this function can write more than it is asked to! + * If addr is not an even 32 bit boundary, or len is not a multiple of 4. + * If only 32 bit values can be written to the target, then this function should read + * the target memory at the start and end of the buffer where it will write more that + * the requested bytes. (perhaps reading the whole area is faster??). + * If 16 and 8 bit writes are available, then they could be used instead. + * Just return when the length is zero avoiding unneeded work. */ + if (len == 0) { return(0); } int offset = addr % 4; int write_len = len + offset; - if (sl == NULL || data == NULL) { - return -1; - } + if (sl == NULL || data == NULL) { return(-1); } - /* Align read size */ - if ((write_len % 4) != 0) { - write_len += 4 - (write_len % 4); - } + // align read size + if ((write_len % 4) != 0) { write_len += 4 - (write_len % 4); } memcpy(&sl->q_buf[offset], data, len); - /* Address and length must be aligned */ - if (stlink_write_mem32(sl, addr - offset, write_len) != 0) { - return -1; - } + // address and length must be aligned + if (stlink_write_mem32(sl, addr - offset, write_len) != 0) { return(-1); } - return 0; + return(0); } /* For the SYS_WRITE0 call, we don't know the size of the null-terminated buffer @@ -162,9 +129,7 @@ static int saved_errno = 0; int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { - if (sl == NULL || ret == NULL) { - return -1; - } + if (sl == NULL || ret == NULL) { return(-1); } DLOG("Do semihosting R0=0x%08x R1=0x%08x\n", r0, r1); @@ -177,11 +142,10 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { uint32_t name_len; char *name; - if (mem_read(sl, r1, args, sizeof (args)) != 0){ - DLOG("Semihosting SYS_OPEN error: " - "cannot read args from target memory\n"); + if (mem_read(sl, r1, args, sizeof(args)) != 0) { + DLOG("Semihosting SYS_OPEN error: cannot read args from target memory\n"); *ret = -1; - return -1; + return(-1); } name_address = args[0]; @@ -192,7 +156,7 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { /* Invalid mode */ DLOG("Semihosting SYS_OPEN error: invalid mode %d\n", mode); *ret = -1; - return -1; + return(-1); } /* Add the trailing zero that is not counted in the length argument (see @@ -201,25 +165,24 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { name_len += 1; if (name_len > MAX_BUFFER_SIZE) { - DLOG("Semihosting SYS_OPEN error: name buffer size is too big %d\n", - name_len); + DLOG("Semihosting SYS_OPEN error: name buffer size is too big %d\n", name_len); *ret = -1; - return -1; + return(-1); } + name = malloc(name_len); if (name == NULL) { DLOG("Semihosting SYS_OPEN error: cannot allocate name buffer\n"); *ret = -1; - return -1; + return(-1); } - if (mem_read(sl, name_address, name, name_len) != 0){ + if (mem_read(sl, name_address, name, name_len) != 0) { free(name); *ret = -1; - DLOG("Semihosting SYS_OPEN error: " - "cannot read name from target memory\n"); - return -1; + DLOG("Semihosting SYS_OPEN error: cannot read name from target memory\n"); + return(-1); } DLOG("Semihosting: open('%s', (SH open mode)%d, 0644)\n", name, mode); @@ -235,13 +198,12 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { case SEMIHOST_SYS_CLOSE: { uint32_t args[1]; - int fd; + int fd; - if (mem_read(sl, r1, args, sizeof (args)) != 0){ - DLOG("Semihosting SYS_CLOSE error: " - "cannot read args from target memory\n"); + if (mem_read(sl, r1, args, sizeof(args)) != 0) { + DLOG("Semihosting SYS_CLOSE error: cannot read args from target memory\n"); *ret = -1; - return -1; + return(-1); } fd = (int)args[0]; @@ -258,15 +220,14 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { { uint32_t args[3]; uint32_t buffer_address; - int fd; + int fd; uint32_t buffer_len; void *buffer; - if (mem_read(sl, r1, args, sizeof (args)) != 0){ - DLOG("Semihosting SYS_WRITE error: " - "cannot read args from target memory\n"); + if (mem_read(sl, r1, args, sizeof(args)) != 0) { + DLOG("Semihosting SYS_WRITE error: cannot read args from target memory\n"); *ret = -1; - return -1; + return(-1); } fd = (int)args[0]; @@ -275,9 +236,9 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { if (buffer_len > MAX_BUFFER_SIZE) { DLOG("Semihosting SYS_WRITE error: buffer size is too big %d\n", - buffer_len); + buffer_len); *ret = buffer_len; - return -1; + return(-1); } buffer = malloc(buffer_len); @@ -285,19 +246,18 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { if (buffer == NULL) { DLOG("Semihosting SYS_WRITE error: cannot allocate buffer\n"); *ret = buffer_len; - return -1; + return(-1); } - if (mem_read(sl, buffer_address, buffer, buffer_len) != 0){ - DLOG("Semihosting SYS_WRITE error: " - "cannot read buffer from target memory\n"); + if (mem_read(sl, buffer_address, buffer, buffer_len) != 0) { + DLOG("Semihosting SYS_WRITE error: cannot read buffer from target memory\n"); free(buffer); *ret = buffer_len; - return -1; + return(-1); } - DLOG("Semihosting: write(%d, target_addr:0x%08x, %zu)\n", fd, - buffer_address, buffer_len); + DLOG("Semihosting: write(%d, target_addr:0x%08x, %zu)\n", fd, buffer_address, + buffer_len); *ret = (uint32_t)write(fd, buffer, buffer_len); saved_errno = errno; @@ -316,16 +276,15 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { { uint32_t args[3]; uint32_t buffer_address; - int fd; + int fd; uint32_t buffer_len; void *buffer; - ssize_t read_result; + ssize_t read_result; - if (mem_read(sl, r1, args, sizeof (args)) != 0){ - DLOG("Semihosting SYS_READ error: " - "cannot read args from target memory\n"); + if (mem_read(sl, r1, args, sizeof(args)) != 0) { + DLOG("Semihosting SYS_READ error: cannot read args from target memory\n"); *ret = -1; - return -1; + return(-1); } fd = (int)args[0]; @@ -333,10 +292,9 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { buffer_len = args[2]; if (buffer_len > MAX_BUFFER_SIZE) { - DLOG("Semihosting SYS_READ error: buffer size is too big %d\n", - buffer_len); + DLOG("Semihosting SYS_READ error: buffer size is too big %d\n", buffer_len); *ret = buffer_len; - return -1; + return(-1); } buffer = malloc(buffer_len); @@ -344,11 +302,11 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { if (buffer == NULL) { DLOG("Semihosting SYS_READ error: cannot allocatebuffer\n"); *ret = buffer_len; - return -1; + return(-1); } - DLOG("Semihosting: read(%d, target_addr:0x%08x, %zu)\n", fd, - buffer_address, buffer_len); + DLOG("Semihosting: read(%d, target_addr:0x%08x, %zu)\n", fd, buffer_address, + buffer_len); read_result = read(fd, buffer, buffer_len); saved_errno = errno; @@ -356,12 +314,11 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { if (read_result == -1) { *ret = buffer_len; } else { - if (mem_write(sl, buffer_address, buffer, read_result) != 0){ - DLOG("Semihosting SYS_READ error: " - "cannot write buffer to target memory\n"); + if (mem_write(sl, buffer_address, buffer, read_result) != 0) { + DLOG("Semihosting SYS_READ error: cannot write buffer to target memory\n"); free(buffer); *ret = buffer_len; - return -1; + return(-1); } else { *ret = buffer_len - (uint32_t)read_result; } @@ -384,11 +341,10 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { uint32_t name_len; char *name; - if (mem_read(sl, r1, args, sizeof (args)) != 0){ - DLOG("Semihosting SYS_REMOVE error: " - "cannot read args from target memory\n"); + if (mem_read(sl, r1, args, sizeof(args)) != 0) { + DLOG("Semihosting SYS_REMOVE error: cannot read args from target memory\n"); *ret = -1; - return -1; + return(-1); } name_address = args[0]; @@ -400,74 +356,68 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { name_len += 1; if (name_len > MAX_BUFFER_SIZE) { - DLOG("Semihosting SYS_REMOVE error: " - "name buffer size is too big %d\n", name_len); + DLOG("Semihosting SYS_REMOVE error: name buffer size is too big %d\n", + name_len); *ret = -1; - return -1; + return(-1); } + name = malloc(name_len); if (name == NULL) { DLOG("Semihosting SYS_REMOVE error: cannot allocate name buffer\n"); *ret = -1; - return -1; + return(-1); } - if (mem_read(sl, name_address, name, name_len) != 0){ + if (mem_read(sl, name_address, name, name_len) != 0) { free(name); *ret = -1; - DLOG("Semihosting SYS_REMOVE error: " - "cannot read name from target memory\n"); - return -1; + DLOG("Semihosting SYS_REMOVE error: cannot read name from target memory\n"); + return(-1); } DLOG("Semihosting: unlink('%s')\n", name); - *ret = (uint32_t)unlink(name); saved_errno = errno; - DLOG("Semihosting: return %d\n", *ret); - free(name); break; } case SEMIHOST_SYS_SEEK: { uint32_t args[2]; - int fd; - off_t offset; + int fd; + off_t offset; - if (mem_read(sl, r1, args, sizeof (args)) != 0){ - DLOG("Semihosting SYS_SEEK error: " - "cannot read args from target memory\n"); + if (mem_read(sl, r1, args, sizeof(args)) != 0) { + DLOG("Semihosting SYS_SEEK error: cannot read args from target memory\n"); *ret = -1; - return -1; + return(-1); } fd = (int)args[0]; offset = (off_t)args[1]; DLOG("Semihosting: lseek(%d, %d, SEEK_SET)\n", fd, offset); - *ret = (uint32_t)lseek(fd, offset, SEEK_SET); saved_errno = errno; - if (*ret != (uint32_t)-1) { - /* Success */ - *ret = 0; - } + if (*ret != (uint32_t)-1) { *ret = 0; /* Success */ } + DLOG("Semihosting: return %d\n", *ret); break; } case SEMIHOST_SYS_WRITEC: { uint8_t c; + if (mem_read_u8(sl, r1, &c) == 0) { fprintf(stderr, "%c", c); } else { - DLOG("Semihosting WRITEC: " - "cannot read target memory at 0x%08x\n", r1); + DLOG("Semihosting WRITEC: cannot read target memory at 0x%08x\n", r1); } + break; } case SEMIHOST_SYS_READC: @@ -481,24 +431,25 @@ int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret) { uint8_t buf[WRITE0_BUFFER_SIZE]; while (true) { - if (mem_read(sl, r1, buf, WRITE0_BUFFER_SIZE) != 0){ - DLOG("Semihosting WRITE0: " - "cannot read target memory at 0x%08x\n", r1); - return -1; + if (mem_read(sl, r1, buf, WRITE0_BUFFER_SIZE) != 0) { + DLOG("Semihosting WRITE0: cannot read target memory at 0x%08x\n", r1); + return(-1); } + for (int i = 0; i < WRITE0_BUFFER_SIZE; i++) { - if (buf[i] == 0) { - return 0; - } + if (buf[i] == 0) { return(0); } + fprintf(stderr, "%c", buf[i]); } + r1 += WRITE0_BUFFER_SIZE; } + break; } default: fprintf(stderr, "semihosting: unsupported call %#x\n", r0); - return -1; + return(-1); } - return 0; + return(0); } diff --git a/src/st-util/semihosting.h b/src/st-util/semihosting.h index 8157df9df..8c1ac15f0 100644 --- a/src/st-util/semihosting.h +++ b/src/st-util/semihosting.h @@ -29,6 +29,6 @@ #define SEMIHOST_SYS_ELAPSED 0x30 #define SEMIHOST_SYS_TICKFREQ 0x31 -int do_semihosting (stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret); +int do_semihosting(stlink_t *sl, uint32_t r0, uint32_t r1, uint32_t *ret); -#endif /* ! _SEMIHOSTING_H_ */ +#endif // _SEMIHOSTING_H_ diff --git a/src/stlink-gui/CMakeLists.txt b/src/stlink-gui/CMakeLists.txt index cc68509fe..89e5403d8 100644 --- a/src/stlink-gui/CMakeLists.txt +++ b/src/stlink-gui/CMakeLists.txt @@ -2,7 +2,10 @@ # Build GUI ### -if (NOT WIN32) +if (NOT WIN32 AND NOT CMAKE_CROSSCOMPILING) + find_package(PkgConfig) + pkg_check_modules(GTK3 gtk+-3.0) + ## GUI-Building requires the presence of a GTK3 toolset if (NOT GTK3_FOUND) message(STATUS "GTK3 not found!") @@ -35,7 +38,5 @@ if (NOT WIN32) COMPILE_DEFINITIONS STLINK_UI_DIR="${CMAKE_INSTALL_PREFIX}/bin") target_link_libraries(stlink-gui ${STLINK_LIB_SHARED} ${SSP_LIB} ${GTK3_LDFLAGS}) install(TARGETS stlink-gui DESTINATION ${CMAKE_INSTALL_BINDIR}) - - endif () endif () diff --git a/src/stlink-gui/gui.c b/src/stlink-gui/gui.c index 7ae591f2d..ed38fcc7c 100644 --- a/src/stlink-gui/gui.c +++ b/src/stlink-gui/gui.c @@ -13,23 +13,23 @@ #define G_VALUE_INIT {0, {{0}}} #endif -G_DEFINE_TYPE (STlinkGUI, stlink_gui, G_TYPE_OBJECT); +G_DEFINE_TYPE(STlinkGUI, stlink_gui, G_TYPE_OBJECT); -static void stlink_gui_dispose (GObject *gobject) { - G_OBJECT_CLASS (stlink_gui_parent_class)->dispose (gobject); +static void stlink_gui_dispose(GObject *gobject) { + G_OBJECT_CLASS(stlink_gui_parent_class)->dispose(gobject); } -static void stlink_gui_finalize (GObject *gobject) { - G_OBJECT_CLASS (stlink_gui_parent_class)->finalize (gobject); +static void stlink_gui_finalize(GObject *gobject) { + G_OBJECT_CLASS(stlink_gui_parent_class)->finalize(gobject); } -static void stlink_gui_class_init (STlinkGUIClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); +static void stlink_gui_class_init(STlinkGUIClass *klass) { + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->dispose = stlink_gui_dispose; gobject_class->finalize = stlink_gui_finalize; } -static void stlink_gui_init (STlinkGUI *self) { +static void stlink_gui_init(STlinkGUI *self) { self->sl = NULL; self->filename = NULL; @@ -45,162 +45,159 @@ static void stlink_gui_init (STlinkGUI *self) { self->file_mem.base = 0; } -static gboolean set_info_error_message_idle (STlinkGUI *gui) { +static gboolean set_info_error_message_idle(STlinkGUI *gui) { if (gui->error_message != NULL) { gchar *markup; - markup = g_markup_printf_escaped ("%s", gui->error_message); - gtk_label_set_markup (gui->infolabel, markup); - gtk_info_bar_set_message_type (gui->infobar, GTK_MESSAGE_ERROR); - gtk_widget_show (GTK_WIDGET (gui->infobar)); + markup = g_markup_printf_escaped("%s", gui->error_message); + gtk_label_set_markup(gui->infolabel, markup); + gtk_info_bar_set_message_type(gui->infobar, GTK_MESSAGE_ERROR); + gtk_widget_show(GTK_WIDGET(gui->infobar)); - g_free (markup); - g_free (gui->error_message); + g_free(markup); + g_free(gui->error_message); gui->error_message = NULL; } - return FALSE; + + return(FALSE); } -static void stlink_gui_set_info_error_message (STlinkGUI *gui, const gchar *message) { - gui->error_message = g_strdup (message); - g_idle_add ((GSourceFunc) set_info_error_message_idle, gui); +static void stlink_gui_set_info_error_message(STlinkGUI *gui, const gchar *message) { + gui->error_message = g_strdup(message); + g_idle_add((GSourceFunc)set_info_error_message_idle, gui); } -static void stlink_gui_set_sensitivity (STlinkGUI *gui, gboolean sensitivity) { - gtk_widget_set_sensitive (GTK_WIDGET (gui->open_button), sensitivity); - if (sensitivity && gui->sl) - gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), sensitivity); - if (sensitivity && !gui->sl) - gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), sensitivity); - if (sensitivity && gui->sl && gui->filename) - gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), sensitivity); - gtk_widget_set_sensitive (GTK_WIDGET (gui->export_button), sensitivity && (gui->sl != NULL)); +static void stlink_gui_set_sensitivity(STlinkGUI *gui, gboolean sensitivity) { + gtk_widget_set_sensitive(GTK_WIDGET(gui->open_button), sensitivity); + + if (sensitivity && gui->sl) { + gtk_widget_set_sensitive(GTK_WIDGET(gui->disconnect_button), sensitivity); + } + + if (sensitivity && !gui->sl) { + gtk_widget_set_sensitive(GTK_WIDGET(gui->connect_button), sensitivity); + } + + if (sensitivity && gui->sl && gui->filename) { + gtk_widget_set_sensitive(GTK_WIDGET(gui->flash_button), sensitivity); + } + + gtk_widget_set_sensitive(GTK_WIDGET(gui->export_button), sensitivity && (gui->sl != NULL)); } -static void mem_view_init_headers (GtkTreeView *view) { +static void mem_view_init_headers(GtkTreeView *view) { GtkCellRenderer *renderer; - gint i; - - g_return_if_fail (view != NULL); - - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes ( - view, - -1, - "Address", - renderer, - "text", - 0, /* column */ - NULL); + gint i; + + g_return_if_fail(view != NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, "Address", renderer, "text", 0, /* column */ NULL); + for (i = 0; i < 4; i++) { gchar *label; - label = g_strdup_printf ("%X", i * 4); - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (view, - -1, - label, - renderer, - "text", - (i + 1), /* column */ - NULL); - g_free (label); + label = g_strdup_printf("%X", i * 4); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, label, renderer, "text", (i + 1), /* column */ NULL); + g_free(label); } for (i = 0; i < 5; i++) { - GtkTreeViewColumn *column = gtk_tree_view_get_column (view, i); - gtk_tree_view_column_set_expand (column, TRUE); + GtkTreeViewColumn *column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_expand(column, TRUE); } } -static void mem_view_add_as_hex ( - GtkListStore *store, - GtkTreeIter *iter, - gint column, - guint32 value) { +static void mem_view_add_as_hex(GtkListStore *store, + GtkTreeIter *iter, + gint column, + guint32 value) { gchar *hex_str; - hex_str = g_strdup_printf ("0x%08X", value); + hex_str = g_strdup_printf("0x%08X", value); gtk_list_store_set(store, iter, column, hex_str, -1); - g_free (hex_str); + g_free(hex_str); } -static void mem_view_add_buffer ( - GtkListStore *store, - GtkTreeIter *iter, - guint32 address, - guchar *buffer, - gint len) { +static void mem_view_add_buffer(GtkListStore *store, + GtkTreeIter *iter, + guint32 address, + guchar *buffer, + gint len) { guint32 *word; - gint i, step; - gint column = 0; + gint i, step; + gint column = 0; - step = sizeof (*word); + step = sizeof(*word); for (i = 0; i < len; i += step) { - word = (guint *) &buffer[i]; + word = (guint *)&buffer[i]; if (column == 0) { - /* new row */ - gtk_list_store_append (store, iter); - - /* add address */ - mem_view_add_as_hex (store, iter, column, (address + i)); + gtk_list_store_append(store, iter); // new row + mem_view_add_as_hex(store, iter, column, (address + i)); // add address } - mem_view_add_as_hex (store, iter, (column + 1), *word); + + mem_view_add_as_hex(store, iter, (column + 1), *word); column = (column + 1) % step; } } -static guint32 hexstr_to_guint32 (const gchar *str, GError **err) { - guint32 val; - gchar *end_ptr; +static guint32 hexstr_to_guint32(const gchar *str, GError **err) { + guint32 val; + gchar *end_ptr; + + val = (guint32)strtoul(str, &end_ptr, 16); - val = (guint32) strtoul (str, &end_ptr, 16); if ((errno == ERANGE && val == UINT_MAX) || (errno != 0 && val == 0)) { - g_set_error (err, g_quark_from_string ("hextou32"), 1, "Invalid hexstring"); - return UINT32_MAX; + g_set_error(err, g_quark_from_string("hextou32"), 1, "Invalid hexstring"); + return(UINT32_MAX); } + if (end_ptr == str) { - g_set_error (err, g_quark_from_string ("hextou32"), 2, "Invalid hexstring"); - return UINT32_MAX; + g_set_error(err, g_quark_from_string("hextou32"), 2, "Invalid hexstring"); + return(UINT32_MAX); } - return val; + + return(val); } -static void stlink_gui_update_mem_view (STlinkGUI *gui, struct mem_t *mem, GtkTreeView *view) { +static void stlink_gui_update_mem_view(STlinkGUI *gui, struct mem_t *mem, GtkTreeView *view) { GtkListStore *store; - GtkTreeIter iter; + GtkTreeIter iter; - store = GTK_LIST_STORE (gtk_tree_view_get_model (view)); + store = GTK_LIST_STORE(gtk_tree_view_get_model(view)); - mem_view_add_buffer (store, &iter, mem->base, mem->memory, (gint) mem->size); + mem_view_add_buffer(store, &iter, mem->base, mem->memory, (gint)mem->size); - gtk_widget_hide (GTK_WIDGET (gui->progress.bar)); - gtk_progress_bar_set_fraction (gui->progress.bar, 0); - stlink_gui_set_sensitivity (gui, TRUE); + gtk_widget_hide(GTK_WIDGET(gui->progress.bar)); + gtk_progress_bar_set_fraction(gui->progress.bar, 0); + stlink_gui_set_sensitivity(gui, TRUE); } -static gboolean stlink_gui_update_devmem_view (STlinkGUI *gui) { - stlink_gui_update_mem_view (gui, &gui->flash_mem, gui->devmem_treeview); - return FALSE; +static gboolean stlink_gui_update_devmem_view(STlinkGUI *gui) { + stlink_gui_update_mem_view(gui, &gui->flash_mem, gui->devmem_treeview); + return(FALSE); } -static gpointer stlink_gui_populate_devmem_view (gpointer data) { - guint off; - stm32_addr_t addr; +static gpointer stlink_gui_populate_devmem_view(gpointer data) { + guint off; + stm32_addr_t addr; - g_return_val_if_fail (STLINK_IS_GUI (data), NULL); + g_return_val_if_fail(STLINK_IS_GUI(data), NULL); STlinkGUI *gui = (STlinkGUI *)data; - g_return_val_if_fail ((gui != NULL), NULL); - g_return_val_if_fail ((gui->sl != NULL), NULL); + g_return_val_if_fail((gui != NULL), NULL); + g_return_val_if_fail((gui->sl != NULL), NULL); addr = gui->sl->flash_base; - if (gui->flash_mem.memory) - g_free (gui->flash_mem.memory); - gui->flash_mem.memory = g_malloc (gui->sl->flash_size); + if (gui->flash_mem.memory) { + g_free(gui->flash_mem.memory); + } + + gui->flash_mem.memory = g_malloc(gui->sl->flash_size); gui->flash_mem.size = gui->sl->flash_size; gui->flash_mem.base = gui->sl->flash_base; @@ -208,304 +205,319 @@ static gpointer stlink_gui_populate_devmem_view (gpointer data) { guint n_read = MEM_READ_SIZE; if (off + MEM_READ_SIZE > gui->sl->flash_size) { - n_read = (guint) gui->sl->flash_size - off; + n_read = (guint)gui->sl->flash_size - off; - /* align if needed */ - if (n_read & 3) - n_read = (n_read + 4) & ~(3); + if (n_read & 3) { n_read = (n_read + 4) & ~(3); } // align if needed } - /* reads to sl->q_buf */ - stlink_read_mem32(gui->sl, addr + off, n_read); + + stlink_read_mem32(gui->sl, addr + off, n_read); // reads to sl->q_buf + if (gui->sl->q_len < 0) { - stlink_gui_set_info_error_message (gui, "Failed to read memory"); - g_free (gui->flash_mem.memory); + stlink_gui_set_info_error_message(gui, "Failed to read memory"); + g_free(gui->flash_mem.memory); gui->flash_mem.memory = NULL; - return NULL; + return(NULL); } - memcpy (gui->flash_mem.memory + off, gui->sl->q_buf, n_read); - gui->progress.fraction = (gdouble) (off + n_read) / gui->sl->flash_size; + + memcpy(gui->flash_mem.memory + off, gui->sl->q_buf, n_read); + gui->progress.fraction = (gdouble)(off + n_read) / gui->sl->flash_size; } - g_idle_add ((GSourceFunc) stlink_gui_update_devmem_view, gui); - return NULL; + + g_idle_add((GSourceFunc)stlink_gui_update_devmem_view, gui); + return(NULL); } -static gboolean stlink_gui_update_filemem_view (STlinkGUI *gui) { +static gboolean stlink_gui_update_filemem_view(STlinkGUI *gui) { gchar *basename; - basename = g_path_get_basename (gui->filename); - gtk_notebook_set_tab_label_text (gui->notebook, - GTK_WIDGET (gtk_notebook_get_nth_page (gui->notebook, 1)), basename); - g_free (basename); + basename = g_path_get_basename(gui->filename); + gtk_notebook_set_tab_label_text( + gui->notebook, GTK_WIDGET(gtk_notebook_get_nth_page(gui->notebook, 1)), basename); + g_free(basename); - stlink_gui_update_mem_view (gui, &gui->file_mem, gui->filemem_treeview); - return FALSE; + stlink_gui_update_mem_view(gui, &gui->file_mem, gui->filemem_treeview); + return(FALSE); } -static gpointer stlink_gui_populate_filemem_view (gpointer data) { - guchar buffer[MEM_READ_SIZE]; - GFile *file; - GFileInfo *file_info; +static gpointer stlink_gui_populate_filemem_view(gpointer data) { + guchar buffer[MEM_READ_SIZE]; + GFile *file; + GFileInfo *file_info; GInputStream *input_stream; - gint off; - GError *err = NULL; + gint off; + GError *err = NULL; - g_return_val_if_fail (STLINK_IS_GUI (data), NULL); + g_return_val_if_fail(STLINK_IS_GUI(data), NULL); STlinkGUI *gui = (STlinkGUI *)data; - g_return_val_if_fail (gui != NULL, NULL); - g_return_val_if_fail (gui->filename != NULL, NULL); + g_return_val_if_fail(gui != NULL, NULL); + g_return_val_if_fail(gui->filename != NULL, NULL); - if (g_str_has_suffix (gui->filename, ".hex")) { - // If the file has prefix .hex - try to interpret it as Intel-HEX. - // It's difficult to merge the world of standard functions and GLib, - // so do it simple - load whole file into buffer and copy the data to the - // destination afterwards. - // We loose meanwhile the displaying of the progress and need double memory. + if (g_str_has_suffix(gui->filename, ".hex")) { + /* If the file has prefix .hex - try to interpret it as Intel-HEX. + * It's difficult to merge the world of standard functions and GLib, so do it simple: + * Load whole file into buffer and copy the data to the destination afterwards. + * In the meanwhile we loose the displaying of the progress and need double memory. + */ uint8_t* mem = NULL; - size_t size = 0; + size_t size = 0; uint32_t begin = 0; - int res = stlink_parse_ihex (gui->filename, 0, &mem, &size, &begin); + int res = stlink_parse_ihex(gui->filename, 0, &mem, &size, &begin); if (res == 0) { - if (gui->file_mem.memory) - g_free (gui->file_mem.memory); + if (gui->file_mem.memory) { + g_free(gui->file_mem.memory); + } + gui->file_mem.size = size; - gui->file_mem.memory = g_malloc (size); + gui->file_mem.memory = g_malloc(size); gui->file_mem.base = begin; - memcpy (gui->file_mem.memory, mem, size); + memcpy(gui->file_mem.memory, mem, size); } else { - stlink_gui_set_info_error_message (gui, "Cannot interpret the file as Intel-HEX"); + stlink_gui_set_info_error_message(gui, "Cannot interpret the file as Intel-HEX"); } free(mem); } else { - file = g_file_new_for_path (gui->filename); - input_stream = G_INPUT_STREAM (g_file_read (file, NULL, &err)); + file = g_file_new_for_path(gui->filename); + input_stream = G_INPUT_STREAM(g_file_read(file, NULL, &err)); + if (err) { - stlink_gui_set_info_error_message (gui, err->message); - g_error_free (err); + stlink_gui_set_info_error_message(gui, err->message); + g_error_free(err); goto out; } - file_info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (input_stream), - G_FILE_ATTRIBUTE_STANDARD_SIZE, NULL, &err); + file_info = g_file_input_stream_query_info( + G_FILE_INPUT_STREAM(input_stream), G_FILE_ATTRIBUTE_STANDARD_SIZE, NULL, &err); + if (err) { - stlink_gui_set_info_error_message (gui, err->message); - g_error_free (err); + stlink_gui_set_info_error_message(gui, err->message); + g_error_free(err); goto out_input; } - if (gui->file_mem.memory) - g_free (gui->file_mem.memory); - gui->file_mem.size = g_file_info_get_size (file_info); - gui->file_mem.memory = g_malloc (gui->file_mem.size); - for (off = 0; off < (gint) gui->file_mem.size; off += MEM_READ_SIZE) { + if (gui->file_mem.memory) { g_free(gui->file_mem.memory); } + + gui->file_mem.size = g_file_info_get_size(file_info); + gui->file_mem.memory = g_malloc(gui->file_mem.size); + + for (off = 0; off < (gint)gui->file_mem.size; off += MEM_READ_SIZE) { guint n_read = MEM_READ_SIZE; - if (off + MEM_READ_SIZE > (gint) gui->file_mem.size) - n_read = (guint) gui->file_mem.size - off; + if (off + MEM_READ_SIZE > (gint)gui->file_mem.size) { + n_read = (guint)gui->file_mem.size - off; + } - if (g_input_stream_read (G_INPUT_STREAM (input_stream), - &buffer, n_read, NULL, &err) == -1) { - stlink_gui_set_info_error_message (gui, err->message); - g_error_free (err); + if (g_input_stream_read( + G_INPUT_STREAM(input_stream), &buffer, n_read, NULL, &err) == -1) { + stlink_gui_set_info_error_message(gui, err->message); + g_error_free(err); goto out_input; } - memcpy (gui->file_mem.memory + off, buffer, n_read); - gui->progress.fraction = (gdouble) (off + n_read) / gui->file_mem.size; + + memcpy(gui->file_mem.memory + off, buffer, n_read); + gui->progress.fraction = (gdouble)(off + n_read) / gui->file_mem.size; } - out_input: g_object_unref (input_stream); - out: g_object_unref (file); +out_input: g_object_unref(input_stream); +out: g_object_unref(file); } - g_idle_add ((GSourceFunc) stlink_gui_update_filemem_view, gui); - return NULL; + g_idle_add((GSourceFunc)stlink_gui_update_filemem_view, gui); + return(NULL); } -static void mem_jmp (GtkTreeView *view, - GtkEntry *entry, - guint32 base_addr, - gsize size, - GError **err) { +static void mem_jmp(GtkTreeView *view, + GtkEntry *entry, + guint32 base_addr, + gsize size, + GError **err) { GtkTreeModel *model; - guint32 jmp_addr; - GtkTreeIter iter; + guint32 jmp_addr; + GtkTreeIter iter; - jmp_addr = hexstr_to_guint32 (gtk_entry_get_text (entry), err); - if (err && *err) - return; + jmp_addr = hexstr_to_guint32(gtk_entry_get_text(entry), err); + + if (err && *err) { return; } if (jmp_addr < base_addr || jmp_addr > base_addr + size) { - g_set_error (err, g_quark_from_string ("mem_jmp"), 1, "Invalid address"); + g_set_error(err, g_quark_from_string("mem_jmp"), 1, "Invalid address"); return; } - model = gtk_tree_view_get_model (view); - if (!model) - return; + model = gtk_tree_view_get_model(view); + + if (!model) { return; } - if (gtk_tree_model_get_iter_first (model, &iter)) { + if (gtk_tree_model_get_iter_first(model, &iter)) { do { guint32 addr; - GValue value = G_VALUE_INIT; + GValue value = G_VALUE_INIT; + + gtk_tree_model_get_value(model, &iter, 0, &value); + + if (G_VALUE_HOLDS_STRING(&value)) { + addr = hexstr_to_guint32(g_value_get_string(&value), err); - gtk_tree_model_get_value (model, &iter, 0, &value); - if (G_VALUE_HOLDS_STRING (&value)) { - addr = hexstr_to_guint32 (g_value_get_string (&value), err); if (!*err) { if (addr == (jmp_addr & 0xFFFFFFF0)) { GtkTreeSelection *selection; - GtkTreePath *path; + GtkTreePath *path; - selection = gtk_tree_view_get_selection (view); - path = gtk_tree_model_get_path (model, &iter); + selection = gtk_tree_view_get_selection(view); + path = gtk_tree_model_get_path(model, &iter); - gtk_tree_selection_select_iter (selection, &iter); - gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.0, 0.0); - gtk_tree_path_free (path); + gtk_tree_selection_select_iter(selection, &iter); + gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE, 0.0, 0.0); + gtk_tree_path_free(path); } } } + g_value_unset(&value); - } while (gtk_tree_model_iter_next (model, &iter)); + } while (gtk_tree_model_iter_next(model, &iter)); } } -static void devmem_jmp_cb (GtkWidget *widget, gpointer data) { +static void devmem_jmp_cb(GtkWidget *widget, gpointer data) { STlinkGUI *gui; - GError *err = NULL; - (void) widget; + GError *err = NULL; + (void)widget; - gui = STLINK_GUI (data); + gui = STLINK_GUI(data); - mem_jmp (gui->devmem_treeview, + mem_jmp(gui->devmem_treeview, gui->devmem_jmp_entry, gui->sl->flash_base, gui->sl->flash_size, &err); if (err) { - stlink_gui_set_info_error_message (gui, err->message); - g_error_free (err); + stlink_gui_set_info_error_message(gui, err->message); + g_error_free(err); } } -static void filemem_jmp_cb (GtkWidget *widget, gpointer data) { +static void filemem_jmp_cb(GtkWidget *widget, gpointer data) { STlinkGUI *gui; - GError *err = NULL; - (void) widget; + GError *err = NULL; + (void)widget; - gui = STLINK_GUI (data); + gui = STLINK_GUI(data); - g_return_if_fail (gui->filename != NULL); + g_return_if_fail(gui->filename != NULL); - mem_jmp (gui->filemem_treeview, + mem_jmp(gui->filemem_treeview, gui->filemem_jmp_entry, 0, gui->file_mem.size, &err); if (err) { - stlink_gui_set_info_error_message (gui, err->message); - g_error_free (err); + stlink_gui_set_info_error_message(gui, err->message); + g_error_free(err); } } -static gchar *dev_format_chip_id (guint32 chip_id) { +static gchar *dev_format_chip_id(guint32 chip_id) { const struct stlink_chipid_params *params; params = stlink_chipid_get_params(chip_id); - if (!params) - return g_strdup_printf ("0x%x", chip_id); - return g_strdup (params->description); + if (!params) { return(g_strdup_printf("0x%x", chip_id)); } + + return(g_strdup(params->description)); } -static gchar *dev_format_mem_size (gsize flash_size) { - return g_strdup_printf ("%u kB", (unsigned int)(flash_size / 1024)); +static gchar *dev_format_mem_size(gsize flash_size) { + return(g_strdup_printf("%u kB", (unsigned int)(flash_size / 1024))); } -static void stlink_gui_set_connected (STlinkGUI *gui) { - gchar *tmp_str; +static void stlink_gui_set_connected(STlinkGUI *gui) { + gchar *tmp_str; GtkListStore *store; - GtkTreeIter iter; + GtkTreeIter iter; + + gtk_statusbar_push(gui->statusbar, gtk_statusbar_get_context_id(gui->statusbar, "conn"), "Connected"); - gtk_statusbar_push (gui->statusbar, - gtk_statusbar_get_context_id (gui->statusbar, "conn"), "Connected"); + gtk_widget_set_sensitive(GTK_WIDGET(gui->device_frame), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(gui->devmem_box), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(gui->connect_button), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (gui->devmem_box), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), FALSE); + if (gui->filename) { + gtk_widget_set_sensitive(GTK_WIDGET(gui->flash_button), TRUE); + } - if (gui->filename) - gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), TRUE); + tmp_str = dev_format_chip_id(gui->sl->chip_id); + gtk_label_set_text(gui->chip_id_label, tmp_str); + g_free(tmp_str); - tmp_str = dev_format_chip_id (gui->sl->chip_id); - gtk_label_set_text (gui->chip_id_label, tmp_str); - g_free (tmp_str); + tmp_str = g_strdup_printf("0x%x", gui->sl->core_id); + gtk_label_set_text(gui->core_id_label, tmp_str); + g_free(tmp_str); - tmp_str = g_strdup_printf ("0x%x", gui->sl->core_id); - gtk_label_set_text (gui->core_id_label, tmp_str); - g_free (tmp_str); + tmp_str = dev_format_mem_size(gui->sl->flash_size); + gtk_label_set_text(gui->flash_size_label, tmp_str); + g_free(tmp_str); - tmp_str = dev_format_mem_size (gui->sl->flash_size); - gtk_label_set_text (gui->flash_size_label, tmp_str); - g_free (tmp_str); + tmp_str = dev_format_mem_size(gui->sl->sram_size); + gtk_label_set_text(gui->ram_size_label, tmp_str); + g_free(tmp_str); - tmp_str = dev_format_mem_size (gui->sl->sram_size); - gtk_label_set_text (gui->ram_size_label, tmp_str); - g_free (tmp_str); + tmp_str = g_strdup_printf("0x%08X", gui->sl->flash_base); + gtk_entry_set_text(gui->devmem_jmp_entry, tmp_str); + gtk_editable_set_editable(GTK_EDITABLE(gui->devmem_jmp_entry), TRUE); + g_free(tmp_str); - tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base); - gtk_entry_set_text (gui->devmem_jmp_entry, tmp_str); - gtk_editable_set_editable (GTK_EDITABLE (gui->devmem_jmp_entry), TRUE); - g_free (tmp_str); + store = GTK_LIST_STORE(gtk_tree_view_get_model(gui->devmem_treeview)); - store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview)); - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) - gtk_list_store_clear (store); + if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) { + gtk_list_store_clear(store); + } - stlink_gui_set_sensitivity (gui, FALSE); - gtk_notebook_set_current_page (gui->notebook, PAGE_DEVMEM); - gtk_widget_show (GTK_WIDGET (gui->progress.bar)); - gtk_progress_bar_set_text (gui->progress.bar, "Reading memory"); + stlink_gui_set_sensitivity(gui, FALSE); + gtk_notebook_set_current_page(gui->notebook, PAGE_DEVMEM); + gtk_widget_show(GTK_WIDGET(gui->progress.bar)); + gtk_progress_bar_set_text(gui->progress.bar, "Reading memory"); - g_thread_new ("devmem", (GThreadFunc) stlink_gui_populate_devmem_view, gui); + g_thread_new("devmem", (GThreadFunc)stlink_gui_populate_devmem_view, gui); } -static void connect_button_cb (GtkWidget *widget, gpointer data) { +static void connect_button_cb(GtkWidget *widget, gpointer data) { STlinkGUI *gui; - gint i; - (void) widget; + gint i; + (void)widget; - gui = STLINK_GUI (data); + gui = STLINK_GUI(data); - if (gui->sl != NULL) - return; + if (gui->sl != NULL) { return; } + + gui->sl = stlink_v1_open(0, 1); // try version 1 then version 2 + + if (gui->sl == NULL) { gui->sl = stlink_open_usb(0, 1, NULL, 0); } - /* try version 1 then version 2 */ - gui->sl = stlink_v1_open(0, 1); - if (gui->sl == NULL) - gui->sl = stlink_open_usb(0, 1, NULL, 0); if (gui->sl == NULL) { - stlink_gui_set_info_error_message (gui, "Failed to connect to STLink."); + stlink_gui_set_info_error_message(gui, "Failed to connect to STLink."); return; } - /* code below taken from flash/main.c, refactoring might be in order */ - if (stlink_current_mode(gui->sl) == STLINK_DEV_DFU_MODE) + // code below taken from flash/main.c, refactoring might be in order + if (stlink_current_mode(gui->sl) == STLINK_DEV_DFU_MODE) { stlink_exit_dfu_mode(gui->sl); + } - if (stlink_current_mode(gui->sl) != STLINK_DEV_DEBUG_MODE) + if (stlink_current_mode(gui->sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(gui->sl); + } - /* Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 */ + // disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 if (gui->sl->chip_id == STLINK_CHIPID_STM32_F4) { memset(gui->sl->q_buf, 0, 4); + for (i = 0; i < 8; i++) { stlink_write_mem32(gui->sl, 0x40026000 + 0x10 + 0x18 * i, 4); stlink_write_mem32(gui->sl, 0x40026400 + 0x10 + 0x18 * i, 4); @@ -513,128 +525,133 @@ static void connect_button_cb (GtkWidget *widget, gpointer data) { stlink_write_mem32(gui->sl, 0x40026400 + 0x24 + 0x18 * i, 4); } } - stlink_gui_set_connected (gui); + + stlink_gui_set_connected(gui); } -static void stlink_gui_set_disconnected (STlinkGUI *gui) { - gtk_statusbar_push (gui->statusbar, - gtk_statusbar_get_context_id (gui->statusbar, "conn"), - "Disconnected"); +static void stlink_gui_set_disconnected(STlinkGUI *gui) { + gtk_statusbar_push(gui->statusbar, gtk_statusbar_get_context_id(gui->statusbar, "conn"), "Disconnected"); - gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (gui->export_button), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(gui->device_frame), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(gui->flash_button), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(gui->export_button), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(gui->disconnect_button), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(gui->connect_button), TRUE); } -static void disconnect_button_cb (GtkWidget *widget, gpointer data) { +static void disconnect_button_cb(GtkWidget *widget, gpointer data) { STlinkGUI *gui; - (void) widget; + (void)widget; - gui = STLINK_GUI (data); + gui = STLINK_GUI(data); if (gui->sl != NULL) { stlink_exit_debug_mode(gui->sl); stlink_close(gui->sl); gui->sl = NULL; } - stlink_gui_set_disconnected (gui); + + stlink_gui_set_disconnected(gui); } -static void stlink_gui_open_file (STlinkGUI *gui) { - GtkWidget *dialog; +static void stlink_gui_open_file(STlinkGUI *gui) { + GtkWidget *dialog; GtkListStore *store; - GtkTreeIter iter; + GtkTreeIter iter; - dialog = gtk_file_chooser_dialog_new ("Open file", - gui->window, - GTK_FILE_CHOOSER_ACTION_OPEN, - "_Cancel", GTK_RESPONSE_CANCEL, - "_Open", GTK_RESPONSE_ACCEPT, - NULL); + dialog = gtk_file_chooser_dialog_new("Open file", + gui->window, + GTK_FILE_CHOOSER_ACTION_OPEN, + "_Cancel", GTK_RESPONSE_CANCEL, + "_Open", GTK_RESPONSE_ACCEPT, + NULL); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - gui->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + gui->filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->filemem_treeview)); - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) - gtk_list_store_clear (store); + store = GTK_LIST_STORE(gtk_tree_view_get_model(gui->filemem_treeview)); - stlink_gui_set_sensitivity (gui, FALSE); - gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM); - gtk_widget_show (GTK_WIDGET (gui->progress.bar)); - gtk_progress_bar_set_text (gui->progress.bar, "Reading file"); - g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui); + if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) { + gtk_list_store_clear(store); + } + + stlink_gui_set_sensitivity(gui, FALSE); + gtk_notebook_set_current_page(gui->notebook, PAGE_FILEMEM); + gtk_widget_show(GTK_WIDGET(gui->progress.bar)); + gtk_progress_bar_set_text(gui->progress.bar, "Reading file"); + g_thread_new("file", (GThreadFunc)stlink_gui_populate_filemem_view, gui); } - gtk_widget_destroy (dialog); + + gtk_widget_destroy(dialog); } -static void open_button_cb (GtkWidget *widget, gpointer data) { - STlinkGUI *gui; - (void) widget; +static void open_button_cb(GtkWidget *widget, gpointer data) { + STlinkGUI *gui; + (void)widget; - gui = STLINK_GUI (data); - stlink_gui_open_file (gui); + gui = STLINK_GUI(data); + stlink_gui_open_file(gui); } -static gboolean stlink_gui_write_flash_update (STlinkGUI *gui) { - stlink_gui_set_sensitivity (gui, TRUE); +static gboolean stlink_gui_write_flash_update(STlinkGUI *gui) { + stlink_gui_set_sensitivity(gui, TRUE); gui->progress.activity_mode = FALSE; - gtk_widget_hide (GTK_WIDGET (gui->progress.bar)); - return FALSE; + gtk_widget_hide(GTK_WIDGET(gui->progress.bar)); + return(FALSE); } -static gpointer stlink_gui_write_flash (gpointer data) { - g_return_val_if_fail (STLINK_IS_GUI (data), NULL); +static gpointer stlink_gui_write_flash(gpointer data) { + g_return_val_if_fail(STLINK_IS_GUI(data), NULL); STlinkGUI *gui = (STlinkGUI *)data; - g_return_val_if_fail ((gui->sl != NULL), NULL); - g_return_val_if_fail ((gui->filename != NULL), NULL); + g_return_val_if_fail((gui->sl != NULL), NULL); + g_return_val_if_fail((gui->filename != NULL), NULL); - if (stlink_mwrite_flash(gui->sl, gui->file_mem.memory, - (uint32_t)gui->file_mem.size, gui->sl->flash_base) < 0) { - stlink_gui_set_info_error_message (gui, "Failed to write to flash"); + if (stlink_mwrite_flash( + gui->sl, gui->file_mem.memory, (uint32_t)gui->file_mem.size, gui->sl->flash_base) < 0) { + stlink_gui_set_info_error_message(gui, "Failed to write to flash"); } - g_idle_add ((GSourceFunc) stlink_gui_write_flash_update, gui); - return NULL; + g_idle_add((GSourceFunc)stlink_gui_write_flash_update, gui); + return(NULL); } -static void flash_button_cb (GtkWidget *widget, gpointer data) { +static void flash_button_cb(GtkWidget *widget, gpointer data) { STlinkGUI *gui; - gchar *tmp_str; - guint32 address; - gint result; - GError *err = NULL; - (void) widget; + gchar *tmp_str; + guint32 address; + gint result; + GError *err = NULL; + (void)widget; - gui = STLINK_GUI (data); - g_return_if_fail (gui->sl != NULL); + gui = STLINK_GUI(data); + g_return_if_fail(gui->sl != NULL); - if (!g_strcmp0 (gtk_entry_get_text (gui->flash_dialog_entry), "")) { - tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base); - gtk_entry_set_text (gui->flash_dialog_entry, tmp_str); - g_free (tmp_str); + if (!g_strcmp0(gtk_entry_get_text(gui->flash_dialog_entry), "")) { + tmp_str = g_strdup_printf("0x%08X", gui->sl->flash_base); + gtk_entry_set_text(gui->flash_dialog_entry, tmp_str); + g_free(tmp_str); } - result = gtk_dialog_run (gui->flash_dialog); + result = gtk_dialog_run(gui->flash_dialog); + if (result == GTK_RESPONSE_OK) { - address = hexstr_to_guint32 (gtk_entry_get_text (gui->flash_dialog_entry), &err); + address = hexstr_to_guint32(gtk_entry_get_text(gui->flash_dialog_entry), &err); + if (err) { - stlink_gui_set_info_error_message (gui, err->message); + stlink_gui_set_info_error_message(gui, err->message); } else { if (address > gui->sl->flash_base + gui->sl->flash_size || address < gui->sl->flash_base) { - stlink_gui_set_info_error_message (gui, "Invalid address"); + stlink_gui_set_info_error_message(gui, "Invalid address"); } else if (address + gui->file_mem.size > gui->sl->flash_base + gui->sl->flash_size) { - stlink_gui_set_info_error_message (gui, "Binary overwrites flash"); + stlink_gui_set_info_error_message(gui, "Binary overwrites flash"); } else { - stlink_gui_set_sensitivity (gui, FALSE); - gtk_progress_bar_set_text (gui->progress.bar, "Writing to flash"); + stlink_gui_set_sensitivity(gui, FALSE); + gtk_progress_bar_set_text(gui->progress.bar, "Writing to flash"); gui->progress.activity_mode = TRUE; - gtk_widget_show (GTK_WIDGET (gui->progress.bar)); - g_thread_new ("flash", (GThreadFunc) stlink_gui_write_flash, gui); + gtk_widget_show(GTK_WIDGET(gui->progress.bar)); + g_thread_new("flash", (GThreadFunc)stlink_gui_write_flash, gui); } } } @@ -642,248 +659,258 @@ static void flash_button_cb (GtkWidget *widget, gpointer data) { int export_to_file(const char*filename, const struct mem_t flash_mem) { printf("%s\n", filename); - FILE * f=fopen(filename, "w"); - if (f == NULL) - return -1; - for (gsize i=0;iwindow, - GTK_FILE_CHOOSER_ACTION_SAVE, - "_Cancel", - GTK_RESPONSE_CANCEL, - "_Open", - GTK_RESPONSE_ACCEPT, - NULL); - GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog); - gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE); - gint res = gtk_dialog_run (GTK_DIALOG (dialog)); + dialog = gtk_file_chooser_dialog_new("Save as", + gui->window, + GTK_FILE_CHOOSER_ACTION_SAVE, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Open", + GTK_RESPONSE_ACCEPT, + NULL); + GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog); + gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); + gint res = gtk_dialog_run(GTK_DIALOG(dialog)); + if (res == GTK_RESPONSE_ACCEPT) { char *filename; - filename = gtk_file_chooser_get_filename (chooser); - if (export_to_file (filename, gui->flash_mem) != 0) { + filename = gtk_file_chooser_get_filename(chooser); + + if (export_to_file(filename, gui->flash_mem) != 0) { stlink_gui_set_info_error_message(gui, "Failed to export flash"); } else { stlink_gui_set_info_error_message(gui, "Export successful"); } - g_free (filename); + + g_free(filename); } - gtk_widget_destroy (dialog); + gtk_widget_destroy(dialog); } -static gboolean progress_pulse_timeout (STlinkGUI *gui) { +static gboolean progress_pulse_timeout(STlinkGUI *gui) { if (gui->progress.activity_mode) { - gtk_progress_bar_pulse (gui->progress.bar); + gtk_progress_bar_pulse(gui->progress.bar); } else { - gtk_progress_bar_set_fraction (gui->progress.bar, gui->progress.fraction); + gtk_progress_bar_set_fraction(gui->progress.bar, gui->progress.fraction); } - return TRUE; + + return(TRUE); } -static void notebook_switch_page_cb ( - GtkNotebook *notebook, - GtkWidget *widget, - guint page_num, - gpointer data) { +static void notebook_switch_page_cb(GtkNotebook *notebook, + GtkWidget *widget, + guint page_num, + gpointer data) { STlinkGUI *gui; - (void) notebook; - (void) widget; + (void)notebook; + (void)widget; - gui = STLINK_GUI (data); + gui = STLINK_GUI(data); if (page_num == 1) { - if (gui->filename == NULL) - stlink_gui_open_file (gui); - } -} - -static void dnd_received_cb ( - GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint target_type, - guint timestamp, - gpointer data) { - GFile *file_uri; - gchar **file_list; + if (gui->filename == NULL) { stlink_gui_open_file(gui); } + } +} + +static void dnd_received_cb(GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint target_type, + guint timestamp, + gpointer data) { + GFile *file_uri; + gchar **file_list; const guchar *file_data; - STlinkGUI *gui = STLINK_GUI (data); + STlinkGUI *gui = STLINK_GUI(data); GtkListStore *store; - GtkTreeIter iter; - (void) widget; - (void) x; - (void) y; + GtkTreeIter iter; + (void)widget; + (void)x; + (void)y; - if (selection_data != NULL && gtk_selection_data_get_length (selection_data) > 0) { + if (selection_data != NULL && gtk_selection_data_get_length(selection_data) > 0) { switch (target_type) { case TARGET_FILENAME: - if (gui->filename) - g_free (gui->filename); + if (gui->filename) { + g_free(gui->filename); + } - file_data = gtk_selection_data_get_data (selection_data); - file_list = g_strsplit ((gchar *)file_data, "\r\n", 0); + file_data = gtk_selection_data_get_data(selection_data); + file_list = g_strsplit((gchar *)file_data, "\r\n", 0); - file_uri = g_file_new_for_uri (file_list[0]); - gui->filename = g_file_get_path (file_uri); + file_uri = g_file_new_for_uri(file_list[0]); + gui->filename = g_file_get_path(file_uri); - g_strfreev (file_list); - g_object_unref (file_uri); + g_strfreev(file_list); + g_object_unref(file_uri); - store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview)); - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) - gtk_list_store_clear (store); + store = GTK_LIST_STORE(gtk_tree_view_get_model(gui->devmem_treeview)); + + if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) { + gtk_list_store_clear(store); + } - stlink_gui_set_sensitivity (gui, FALSE); - gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM); - gtk_widget_show (GTK_WIDGET (gui->progress.bar)); - gtk_progress_bar_set_text (gui->progress.bar, "Reading file"); - g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui); + stlink_gui_set_sensitivity(gui, FALSE); + gtk_notebook_set_current_page(gui->notebook, PAGE_FILEMEM); + gtk_widget_show(GTK_WIDGET(gui->progress.bar)); + gtk_progress_bar_set_text(gui->progress.bar, "Reading file"); + g_thread_new("file", (GThreadFunc)stlink_gui_populate_filemem_view, gui); break; } } - gtk_drag_finish ( - context, - TRUE, - gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE, - timestamp); + + gtk_drag_finish( + context, + TRUE, + gdk_drag_context_get_suggested_action(context) == GDK_ACTION_MOVE, + timestamp); } -void stlink_gui_init_dnd (STlinkGUI *gui) { - GtkTargetEntry target_list[] = { { "text/uri-list", 0, TARGET_FILENAME }, }; +void stlink_gui_init_dnd(STlinkGUI *gui) { + GtkTargetEntry target_list[] = { + { "text/uri-list", 0, TARGET_FILENAME }, + }; gtk_drag_dest_set( - GTK_WIDGET (gui->window), - GTK_DEST_DEFAULT_ALL, - target_list, - G_N_ELEMENTS (target_list), - GDK_ACTION_COPY); + GTK_WIDGET(gui->window), + GTK_DEST_DEFAULT_ALL, + target_list, + G_N_ELEMENTS(target_list), + GDK_ACTION_COPY); - g_signal_connect (gui->window, "drag-data-received", G_CALLBACK (dnd_received_cb), gui); + g_signal_connect(gui->window, "drag-data-received", G_CALLBACK(dnd_received_cb), gui); } -static void stlink_gui_build_ui (STlinkGUI *gui) { - GtkBuilder *builder; +static void stlink_gui_build_ui(STlinkGUI *gui) { + GtkBuilder *builder; GtkListStore *devmem_store; GtkListStore *filemem_store; gchar *ui_file = STLINK_UI_DIR "/stlink-gui.ui"; - if (!g_file_test (ui_file, G_FILE_TEST_EXISTS)) ui_file = "stlink-gui.ui"; - builder = gtk_builder_new (); - if (!gtk_builder_add_from_file (builder, ui_file, NULL)) { - g_printerr ("Failed to load UI file: %s\n", ui_file); - exit (1); - } - - gui->window = GTK_WINDOW (gtk_builder_get_object (builder, "window")); - g_signal_connect (G_OBJECT (gui->window), "destroy", G_CALLBACK (gtk_main_quit), NULL); - - /* set up toolutton clicked callbacks */ - gui->open_button = GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "open_button")); - g_signal_connect (G_OBJECT (gui->open_button), "clicked", G_CALLBACK (open_button_cb), gui); - - gui->connect_button = GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "connect_button")); - g_signal_connect (G_OBJECT (gui->connect_button), "clicked", G_CALLBACK (connect_button_cb), gui); - - gui->disconnect_button = GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "disconnect_button")); - g_signal_connect (G_OBJECT (gui->disconnect_button), "clicked", G_CALLBACK (disconnect_button_cb), gui); - - gui->flash_button = GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "flash_button")); - g_signal_connect (G_OBJECT (gui->flash_button), "clicked", G_CALLBACK (flash_button_cb), gui); - - gui->export_button = GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "export_button")); - g_signal_connect (G_OBJECT (gui->export_button), "clicked", G_CALLBACK (export_button_cb), gui); - - gui->devmem_treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "devmem_treeview")); - mem_view_init_headers (gui->devmem_treeview); - devmem_store = gtk_list_store_new (5, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING); - gtk_tree_view_set_model (gui->devmem_treeview, GTK_TREE_MODEL (devmem_store)); - g_object_unref (devmem_store); - - gui->filemem_treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "filemem_treeview")); - mem_view_init_headers (gui->filemem_treeview); - filemem_store = gtk_list_store_new (5, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING); - gtk_tree_view_set_model (gui->filemem_treeview, GTK_TREE_MODEL (filemem_store)); - g_object_unref (filemem_store); - - gui->core_id_label = GTK_LABEL (gtk_builder_get_object (builder, "core_id_value")); - gui->chip_id_label = GTK_LABEL (gtk_builder_get_object (builder, "chip_id_value")); - gui->flash_size_label = GTK_LABEL (gtk_builder_get_object (builder, "flash_size_value")); - gui->ram_size_label = GTK_LABEL (gtk_builder_get_object (builder, "ram_size_value")); - gui->device_frame = GTK_FRAME (gtk_builder_get_object (builder, "device_frame")); - - gui->notebook = GTK_NOTEBOOK (gtk_builder_get_object (builder, "mem_notebook")); - g_signal_connect (gui->notebook, "switch-page", G_CALLBACK (notebook_switch_page_cb), gui); - - gui->devmem_box = GTK_BOX (gtk_builder_get_object (builder, "devmem_box")); - gui->filemem_box = GTK_BOX (gtk_builder_get_object (builder, "filemem_box")); - - gui->devmem_jmp_entry = GTK_ENTRY (gtk_builder_get_object (builder, "devmem_jmp_entry")); - g_signal_connect (gui->devmem_jmp_entry, "activate", G_CALLBACK (devmem_jmp_cb), gui); - - gui->filemem_jmp_entry = GTK_ENTRY (gtk_builder_get_object (builder, "filemem_jmp_entry")); - g_signal_connect (gui->filemem_jmp_entry, "activate", G_CALLBACK (filemem_jmp_cb), gui); - gtk_editable_set_editable (GTK_EDITABLE (gui->filemem_jmp_entry), TRUE); - - gui->progress.bar = GTK_PROGRESS_BAR (gtk_builder_get_object (builder, "progressbar")); - gtk_progress_bar_set_show_text (gui->progress.bar, TRUE); - gui->progress.timer = g_timeout_add (100, (GSourceFunc) progress_pulse_timeout, gui); - - gui->statusbar = GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar")); - - gui->infobar = GTK_INFO_BAR (gtk_builder_get_object (builder, "infobar")); - gtk_info_bar_add_button (gui->infobar, "_OK", GTK_RESPONSE_OK); - gui->infolabel = GTK_LABEL (gtk_label_new ("")); - gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (gui->infobar)), GTK_WIDGET (gui->infolabel)); - g_signal_connect (gui->infobar, "response", G_CALLBACK (gtk_widget_hide), NULL); - - /* flash dialog */ - gui->flash_dialog = GTK_DIALOG (gtk_builder_get_object (builder, "flash_dialog")); - g_signal_connect_swapped (gui->flash_dialog, "response", G_CALLBACK (gtk_widget_hide), gui->flash_dialog); - gui->flash_dialog_ok = GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_ok_button")); - gui->flash_dialog_cancel = GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_cancel_button")); - gui->flash_dialog_entry = GTK_ENTRY (gtk_builder_get_object (builder, "flash_dialog_entry")); - - /* make it so */ - gtk_widget_show_all (GTK_WIDGET (gui->window)); - gtk_widget_hide (GTK_WIDGET (gui->infobar)); - gtk_widget_hide (GTK_WIDGET (gui->progress.bar)); - - stlink_gui_set_disconnected (gui); -} - -int main (int argc, char **argv) { + if (!g_file_test(ui_file, G_FILE_TEST_EXISTS)) { ui_file = "stlink-gui.ui"; } + + builder = gtk_builder_new(); + + if (!gtk_builder_add_from_file(builder, ui_file, NULL)) { + g_printerr("Failed to load UI file: %s\n", ui_file); + exit(1); + } + + gui->window = GTK_WINDOW(gtk_builder_get_object(builder, "window")); + g_signal_connect(G_OBJECT(gui->window), "destroy", G_CALLBACK(gtk_main_quit), NULL); + + /* Setup for toolbutton clicked callbacks */ + gui->open_button = GTK_TOOL_BUTTON(gtk_builder_get_object(builder, "open_button")); + g_signal_connect(G_OBJECT(gui->open_button), "clicked", G_CALLBACK(open_button_cb), gui); + + gui->connect_button = GTK_TOOL_BUTTON(gtk_builder_get_object(builder, "connect_button")); + g_signal_connect(G_OBJECT(gui->connect_button), "clicked", G_CALLBACK(connect_button_cb), gui); + + gui->disconnect_button = GTK_TOOL_BUTTON(gtk_builder_get_object(builder, "disconnect_button")); + g_signal_connect(G_OBJECT(gui->disconnect_button), "clicked", G_CALLBACK(disconnect_button_cb), gui); + + gui->flash_button = GTK_TOOL_BUTTON(gtk_builder_get_object(builder, "flash_button")); + g_signal_connect(G_OBJECT(gui->flash_button), "clicked", G_CALLBACK(flash_button_cb), gui); + + gui->export_button = GTK_TOOL_BUTTON(gtk_builder_get_object(builder, "export_button")); + g_signal_connect(G_OBJECT(gui->export_button), "clicked", G_CALLBACK(export_button_cb), gui); + + gui->devmem_treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "devmem_treeview")); + mem_view_init_headers(gui->devmem_treeview); + devmem_store = gtk_list_store_new(5, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + gtk_tree_view_set_model(gui->devmem_treeview, GTK_TREE_MODEL(devmem_store)); + g_object_unref(devmem_store); + + gui->filemem_treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "filemem_treeview")); + mem_view_init_headers(gui->filemem_treeview); + filemem_store = gtk_list_store_new(5, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + gtk_tree_view_set_model(gui->filemem_treeview, GTK_TREE_MODEL(filemem_store)); + g_object_unref(filemem_store); + + gui->core_id_label = GTK_LABEL(gtk_builder_get_object(builder, "core_id_value")); + gui->chip_id_label = GTK_LABEL(gtk_builder_get_object(builder, "chip_id_value")); + gui->flash_size_label = GTK_LABEL(gtk_builder_get_object(builder, "flash_size_value")); + gui->ram_size_label = GTK_LABEL(gtk_builder_get_object(builder, "ram_size_value")); + gui->device_frame = GTK_FRAME(gtk_builder_get_object(builder, "device_frame")); + + gui->notebook = GTK_NOTEBOOK(gtk_builder_get_object(builder, "mem_notebook")); + g_signal_connect(gui->notebook, "switch-page", G_CALLBACK(notebook_switch_page_cb), gui); + + gui->devmem_box = GTK_BOX(gtk_builder_get_object(builder, "devmem_box")); + gui->filemem_box = GTK_BOX(gtk_builder_get_object(builder, "filemem_box")); + + gui->devmem_jmp_entry = GTK_ENTRY(gtk_builder_get_object(builder, "devmem_jmp_entry")); + g_signal_connect(gui->devmem_jmp_entry, "activate", G_CALLBACK(devmem_jmp_cb), gui); + + gui->filemem_jmp_entry = GTK_ENTRY(gtk_builder_get_object(builder, "filemem_jmp_entry")); + g_signal_connect(gui->filemem_jmp_entry, "activate", G_CALLBACK(filemem_jmp_cb), gui); + gtk_editable_set_editable(GTK_EDITABLE(gui->filemem_jmp_entry), TRUE); + + gui->progress.bar = GTK_PROGRESS_BAR(gtk_builder_get_object(builder, "progressbar")); + gtk_progress_bar_set_show_text(gui->progress.bar, TRUE); + gui->progress.timer = g_timeout_add(100, (GSourceFunc)progress_pulse_timeout, gui); + + gui->statusbar = GTK_STATUSBAR(gtk_builder_get_object(builder, "statusbar")); + + gui->infobar = GTK_INFO_BAR(gtk_builder_get_object(builder, "infobar")); + gtk_info_bar_add_button(gui->infobar, "_OK", GTK_RESPONSE_OK); + gui->infolabel = GTK_LABEL(gtk_label_new("")); + gtk_container_add(GTK_CONTAINER(gtk_info_bar_get_content_area(gui->infobar)), GTK_WIDGET(gui->infolabel)); + g_signal_connect(gui->infobar, "response", G_CALLBACK(gtk_widget_hide), NULL); + + /* Flash dialog */ + gui->flash_dialog = GTK_DIALOG(gtk_builder_get_object(builder, "flash_dialog")); + g_signal_connect_swapped(gui->flash_dialog, "response", G_CALLBACK(gtk_widget_hide), gui->flash_dialog); + gui->flash_dialog_ok = GTK_BUTTON(gtk_builder_get_object(builder, "flash_dialog_ok_button")); + gui->flash_dialog_cancel = GTK_BUTTON(gtk_builder_get_object(builder, "flash_dialog_cancel_button")); + gui->flash_dialog_entry = GTK_ENTRY(gtk_builder_get_object(builder, "flash_dialog_entry")); + + // make it so + gtk_widget_show_all(GTK_WIDGET(gui->window)); + gtk_widget_hide(GTK_WIDGET(gui->infobar)); + gtk_widget_hide(GTK_WIDGET(gui->progress.bar)); + + stlink_gui_set_disconnected(gui); +} + +int main(int argc, char **argv) { STlinkGUI *gui; - gtk_init (&argc, &argv); + gtk_init(&argc, &argv); - gui = g_object_new (STLINK_TYPE_GUI, NULL); - stlink_gui_build_ui (gui); - stlink_gui_init_dnd (gui); + gui = g_object_new(STLINK_TYPE_GUI, NULL); + stlink_gui_build_ui(gui); + stlink_gui_init_dnd(gui); - gtk_main (); - return 0; + gtk_main(); + return(0); } diff --git a/src/stlink-gui/gui.h b/src/stlink-gui/gui.h index c83e638f6..b3d5dfff8 100644 --- a/src/stlink-gui/gui.h +++ b/src/stlink-gui/gui.h @@ -1,19 +1,18 @@ - #ifndef __STLINK_GUI_H__ #define __STLINK_GUI_H__ #include -#define STLINK_TYPE_GUI (stlink_gui_get_type ()) -#define STLINK_GUI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STLINK_TYPE_GUI, STlinkGUI)) -#define STLINK_IS_GUI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STLINK_TYPE_GUI)) -#define STLINK_GUI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STLINK_TYPE_GUI, STlinkGUIClass)) -#define STLINK_IS_GUI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STLINK_TYPE_GUI)) -#define STLINK_GUI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STLINK_TYPE_GUI, STlinkGUIlass)) -#define STLINK_GUI_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), STLINK_TYPE_GUI, STlinkGUIPrivate)) +#define STLINK_TYPE_GUI (stlink_gui_get_type()) +#define STLINK_GUI(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), STLINK_TYPE_GUI, STlinkGUI)) +#define STLINK_IS_GUI(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), STLINK_TYPE_GUI)) +#define STLINK_GUI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), STLINK_TYPE_GUI, STlinkGUIClass)) +#define STLINK_IS_GUI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), STLINK_TYPE_GUI)) +#define STLINK_GUI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), STLINK_TYPE_GUI, STlinkGUIlass)) +#define STLINK_GUI_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), STLINK_TYPE_GUI, STlinkGUIPrivate)) -typedef struct _STlinkGUI STlinkGUI; -typedef struct _STlinkGUIClass STlinkGUIClass; +typedef struct _STlinkGUI STlinkGUI; +typedef struct _STlinkGUIClass STlinkGUIClass; typedef struct _STlinkGUIPrivate STlinkGUIPrivate; enum stlink_gui_pages_t { @@ -28,21 +27,21 @@ enum stlink_gui_dnd_targets_t { struct progress_t { GtkProgressBar *bar; - guint timer; - gboolean activity_mode; - gdouble fraction; + guint timer; + gboolean activity_mode; + gdouble fraction; }; struct mem_t { guchar *memory; - gsize size; + gsize size; guint32 base; }; struct _STlinkGUI { GObject parent_instance; - /*< private >*/ + /* < private > */ GtkWindow *window; GtkTreeView *devmem_treeview; GtkTreeView *filemem_treeview; @@ -72,9 +71,9 @@ struct _STlinkGUI { GtkButton *flash_dialog_cancel; GtkEntry *flash_dialog_entry; - struct progress_t progress; - struct mem_t flash_mem; - struct mem_t file_mem; + struct progress_t progress; + struct mem_t flash_mem; + struct mem_t file_mem; gchar *error_message; gchar *filename; @@ -87,7 +86,7 @@ struct _STlinkGUIClass { /* class members */ }; -GType stlink_gui_get_type (void); +GType stlink_gui_get_type(void); int export_to_file(const char*filename, const struct mem_t flash_mem); -#endif +#endif // __STLINK_GUI_H__ diff --git a/src/stlink-lib/chipid.c b/src/stlink-lib/chipid.c new file mode 100644 index 000000000..bf0a56c96 --- /dev/null +++ b/src/stlink-lib/chipid.c @@ -0,0 +1,638 @@ +#include +#include "chipid.h" + +static const struct stlink_chipid_params devices[] = { + { + // RM0410 document was used to find these paramaters + .chip_id = STLINK_CHIPID_STM32_F7XXXX, + .description = "F76xxx", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1ff0f442, // section 45.2 + .flash_pagesize = 0x800, // No flash pages + .sram_size = 0x80000, // "SRAM" byte size in hex from + .bootrom_base = 0x00200000, // ! "System memory" starting address from + .bootrom_size = 0xEDC0 // ! @todo "System memory" byte size in hex from + }, + { + // RM0385 and DS10916 document was used to find these paramaters + .chip_id = STLINK_CHIPID_STM32_F7, + .description = "F7xx", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1ff0f442, // section 41.2 + .flash_pagesize = 0x800, // No flash pages + .sram_size = 0x50000, // "SRAM" byte size in hex from DS Fig 18 + .bootrom_base = 0x00100000, // "System memory" starting address from DS Fig 18 + .bootrom_size = 0xEDC0 // "System memory" byte size in hex from DS Fig 18 + }, + { + // RM0431 and DS document was used to find these paramaters + .chip_id = STLINK_CHIPID_STM32_F72XXX, + .description = "F72x/F73x", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1ff07a22, // section 35.2 + .flash_pagesize = 0x800, // No flash pages + .sram_size = 0x40000, // "SRAM" byte size in hex from DS Fig 24 + .bootrom_base = 0x00100000, // "System memory" starting address from DS Fig 24 + .bootrom_size = 0xEDC0 // "System memory" byte size in hex from DS Fig 24 + }, + { // table 2, PM0063 + .chip_id = STLINK_CHIPID_STM32_F1_MEDIUM, + .description = "F1xx Medium-density", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7e0, + .flash_pagesize = 0x400, + .sram_size = 0x5000, + .bootrom_base = 0x1ffff000, + .bootrom_size = 0x800 + }, + { // table 1, PM0059 + .chip_id = STLINK_CHIPID_STM32_F2, + .description = "F2xx", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1fff7a22, // as in RM0033 Rev 5 + .flash_pagesize = 0x20000, + .sram_size = 0x20000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800, + .option_base = 0x1FFFC000, + .option_size = 4, + }, + { // PM0063 + .chip_id = STLINK_CHIPID_STM32_F1_LOW, + .description = "F1 Low-density device", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7e0, + .flash_pagesize = 0x400, + .sram_size = 0x2800, + .bootrom_base = 0x1ffff000, + .bootrom_size = 0x800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F4, + .description = "F4xx", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 + .flash_pagesize = 0x4000, + .sram_size = 0x30000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F4_DSI, + .description = "F46x/F47x", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 + .flash_pagesize = 0x4000, + .sram_size = 0x40000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F4_HD, + .description = "F42x/F43x", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, // As in rm0090 since Rev 2 + .flash_pagesize = 0x4000, + .sram_size = 0x40000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F4_LP, + .description = "F4xx (low power)", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, + .flash_pagesize = 0x4000, + .sram_size = 0x10000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F411RE, + .description = "stm32f411re", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, + .flash_pagesize = 0x4000, + .sram_size = 0x20000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F4_DE, + .description = "F4xx (Dynamic Efficency)", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, + .flash_pagesize = 0x4000, + .sram_size = 0x18000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F1_HIGH, + .description = "F1xx High-density", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7e0, + .flash_pagesize = 0x800, + .sram_size = 0x10000, + .bootrom_base = 0x1ffff000, + .bootrom_size = 0x800 + }, + { + // This ignores the EEPROM! (and uses the page erase size, + // not the sector write protection...) + .chip_id = STLINK_CHIPID_STM32_L1_MEDIUM, + .description = "L1xx Medium-density", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff8004c, + .flash_pagesize = 0x100, + .sram_size = 0x4000, + .bootrom_base = 0x1ff00000, + .bootrom_size = 0x1000 + }, + { + .chip_id = STLINK_CHIPID_STM32_L1_CAT2, + .description = "L1xx Cat.2", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff8004c, + .flash_pagesize = 0x100, + .sram_size = 0x8000, + .bootrom_base = 0x1ff00000, + .bootrom_size = 0x1000 + }, + { + .chip_id = STLINK_CHIPID_STM32_L1_MEDIUM_PLUS, + .description = "L1xx Medium-Plus-density", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff800cc, + .flash_pagesize = 0x100, + .sram_size = 0x8000, // not completely clear if there are some with 48k + .bootrom_base = 0x1ff00000, + .bootrom_size = 0x1000 + }, + { + .chip_id = STLINK_CHIPID_STM32_L1_HIGH, + .description = "L1xx High-density", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff800cc, + .flash_pagesize = 0x100, + .sram_size = 0xC000, // not completely clear if there are some with 32k + .bootrom_base = 0x1ff00000, + .bootrom_size = 0x1000, + .option_base = STM32_L1_OPTION_BYTES_BASE, + .option_size = 8, + }, + { + .chip_id = STLINK_CHIPID_STM32_L152_RE, + .description = "L152RE", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff800cc, + .flash_pagesize = 0x100, + .sram_size = 0x14000, // not completely clear if there are some with 32k + .bootrom_base = 0x1ff00000, + .bootrom_size = 0x1000 + }, + { + .chip_id = STLINK_CHIPID_STM32_F1_CONN, + .description = "F1 Connectivity line", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7e0, + .flash_pagesize = 0x800, + .sram_size = 0x10000, + .bootrom_base = 0x1fffb000, + .bootrom_size = 0x4800 + }, + { // Low and Medium density VL have same chipid. RM0041 25.6.1 + .chip_id = STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW, + .description = "F1xx Value Line", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7e0, + .flash_pagesize = 0x400, + .sram_size = 0x2000, // 0x1000 for low density devices + .bootrom_base = 0x1ffff000, + .bootrom_size = 0x800 + }, + { + // STM32F446x family. Support based on DM00135183.pdf (RM0390) document. + .chip_id = STLINK_CHIPID_STM32_F446, + .description = "F446", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1fff7a22, + .flash_pagesize = 0x20000, + .sram_size = 0x20000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800, + .option_base = 0x1FFFC000, + .option_size = 4, + }, + { + // STM32F410 MCUs. Support based on DM00180366.pdf (RM0401) document. + .chip_id = STLINK_CHIPID_STM32_F410, + .description = "F410", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1fff7a22, + .flash_pagesize = 0x4000, + .sram_size = 0x8000, + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7800 + }, + { + // This is STK32F303VCT6 device from STM32 F3 Discovery board. + // Support based on DM00043574.pdf (RM0316) document. + .chip_id = STLINK_CHIPID_STM32_F3, + .description = "F3xx", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, + .flash_pagesize = 0x800, + .sram_size = 0xa000, + .bootrom_base = 0x1ffff000, + .bootrom_size = 0x800 + }, + { + // This is STK32F373VCT6 device from STM32 F373 eval board + // Support based on 303 above (37x and 30x have same memory map) + .chip_id = STLINK_CHIPID_STM32_F37x, + .description = "F3xx", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, + .flash_pagesize = 0x800, + .sram_size = 0xa000, + .bootrom_base = 0x1ffff000, + .bootrom_size = 0x800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F1_VL_HIGH, + .description = "F1xx High-density value line", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7e0, + .flash_pagesize = 0x800, + .sram_size = 0x8000, + .bootrom_base = 0x1ffff000, + .bootrom_size = 0x800 + }, + { + .chip_id = STLINK_CHIPID_STM32_F1_XL, + .description = "F1xx XL-density", + .flash_type = STLINK_FLASH_TYPE_F1_XL, + .flash_size_reg = 0x1ffff7e0, + .flash_pagesize = 0x800, + .sram_size = 0x18000, + .bootrom_base = 0x1fffe000, + .bootrom_size = 0x1800 + }, + { + // Use this as an example for mapping future chips: + // RM0091 document was used to find these paramaters + .chip_id = STLINK_CHIPID_STM32_F0_CAN, + .description = "F07x", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x800, // Page sizes listed in Table 4 + .sram_size = 0x4000, // "SRAM" byte size in hex from Table 2 + .bootrom_base = 0x1fffC800, // "System memory" starting address from Table 2 + .bootrom_size = 0x3000 // "System memory" byte size in hex from Table 2 + }, + { + // Use this as an example for mapping future chips: + // RM0091 document was used to find these paramaters + .chip_id = STLINK_CHIPID_STM32_F0, + .description = "F0xx", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x400, // Page sizes listed in Table 4 + .sram_size = 0x2000, // "SRAM" byte size in hex from Table 2 + .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 + .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2 + }, + { + // RM0402 document was used to find these parameters + // Table 4. + .chip_id = STLINK_CHIPID_STM32_F412, + .description = "F412", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, // "Flash size data register" (pg1135) + .flash_pagesize = 0x4000, // Table 5. Flash module organization ? + .sram_size = 0x40000, // "SRAM" byte size in hex from Table 4 + .bootrom_base = 0x1FFF0000, // "System memory" starting address from Table 4 + .bootrom_size = 0x7800 // "System memory" byte size in hex from Table 4 + }, + { + // RM0430 DocID029473 Rev 2 document was used to find these parameters + // Figure 2, Table 4, Table 5, Section 35.2 + .chip_id = STLINK_CHIPID_STM32_F413, + .description = "F413", + .flash_type = STLINK_FLASH_TYPE_F4, + .flash_size_reg = 0x1FFF7A22, // "Flash size data register" Section 35.2 + .flash_pagesize = 0x4000, // Table 5. Flash module organization (variable sector sizes, but 0x4000 is smallest) + .sram_size = 0x50000, // "SRAM" byte size in hex from Figure 2 (Table 4 only says 0x40000) + .bootrom_base = 0x1FFF0000, // "System memory" starting address from Table 4 + .bootrom_size = 0x7800 // "System memory" byte size in hex from Table 4 + }, + { + .chip_id = STLINK_CHIPID_STM32_F09X, + .description = "F09X", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x800, // Page sizes listed in Table 4 (pg 56) + .sram_size = 0x8000, // "SRAM" byte size in hex from Table 2 (pg 50) + .bootrom_base = 0x1fffd800, // "System memory" starting address from Table 2 + .bootrom_size = 0x2000 // "System memory" byte size in hex from Table 2 + }, + { + // Use this as an example for mapping future chips: + // RM0091 document was used to find these paramaters + .chip_id = STLINK_CHIPID_STM32_F04, + .description = "F04x", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x400, // Page sizes listed in Table 4 + .sram_size = 0x1800, // "SRAM" byte size in hex from Table 2 + .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 + .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2 + }, + { + // Use this as an example for mapping future chips: + // RM0091 document was used to find these paramaters + .chip_id = STLINK_CHIPID_STM32_F0_SMALL, + .description = "F0xx small", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735) + .flash_pagesize = 0x400, // Page sizes listed in Table 4 + .sram_size = 0x1000, // "SRAM" byte size in hex from Table 2 + .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2 + .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2 + }, + { + // STM32F30x + .chip_id = STLINK_CHIPID_STM32_F3_SMALL, + .description = "F3xx small", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, + .flash_pagesize = 0x800, + .sram_size = 0xa000, + .bootrom_base = 0x1fffd800, + .bootrom_size = 0x2000 + }, + { + // STM32L0x + // RM0367,RM0377 documents was used to find these parameters + .chip_id = STLINK_CHIPID_STM32_L0, + .description = "L0x3", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff8007c, + .flash_pagesize = 0x80, + .sram_size = 0x2000, + .bootrom_base = 0x1ff0000, + .bootrom_size = 0x1000, + .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32L0x Category 5 + // RM0367,RM0377 documents was used to find these parameters + .chip_id = STLINK_CHIPID_STM32_L0_CAT5, + .description = "L0xx Category 5", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff8007c, + .flash_pagesize = 0x80, + .sram_size = 0x5000, + .bootrom_base = 0x1ff0000, + .bootrom_size = 0x2000, + .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32L0x Category 2 + // RM0367,RM0377 documents was used to find these parameters + .chip_id = STLINK_CHIPID_STM32_L0_CAT2, + .description = "L0xx Category 2", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff8007c, + .flash_pagesize = 0x80, + .sram_size = 0x2000, + .bootrom_base = 0x1ff0000, + .bootrom_size = 0x1000, + .option_base = STM32_L0_CATx_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32F334, STM32F303x6/8, and STM32F328 + // From RM0364 and RM0316 + .chip_id = STLINK_CHIPID_STM32_F334, + .description = "F334 medium density", // (RM0316 sec 33.6.1) + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, + .flash_pagesize = 0x800, + .sram_size = 0x3000, + .bootrom_base = 0x1fffd800, + .bootrom_size = 0x2000 + }, + { + // This is STK32F303RET6 device from STM32 F3 Nucelo board. + // Support based on DM00043574.pdf (RM0316) document rev 5. + .chip_id = STLINK_CHIPID_STM32_F303_HIGH, + .description = "F303 high density", + .flash_type = STLINK_FLASH_TYPE_F0, + .flash_size_reg = 0x1ffff7cc, // 34.2.1 Flash size data register + .flash_pagesize = 0x800, // 4.2.1 Flash memory organization + .sram_size = 0x10000, // 3.3 Embedded SRAM + .bootrom_base = 0x1fffd800, // 3.3.2 / Table 4 System Memory + .bootrom_size = 0x2000 + }, + { + // STM32L4x6 + // From RM0351. + .chip_id = STLINK_CHIPID_STM32_L4, + .description = "L4xx", + .flash_type = STLINK_FLASH_TYPE_L4, + .flash_size_reg = 0x1FFF75e0, // "Flash size data register" (sec 45.2, page 1671) + .flash_pagesize = 0x800, // 2k (sec 3.2, page 78; also appears in sec 3.3.1 + // and tables 4-6 on pages 79-81) + // SRAM1 is "up to" 96k in the standard Cortex-M memory map; + // SRAM2 is 32k mapped at at 0x10000000 (sec 2.3, page 73 for + // sizes; table 2, page 74 for SRAM2 location) + .sram_size = 0x18000, + .bootrom_base = 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) + .bootrom_size = 0x7000, // 28k (per bank), same source as base + .option_base = STM32_L4_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32L4RX + // From DM00310109.pdf + .chip_id = STLINK_CHIPID_STM32_L4RX, + .description = "L4Rx", + .flash_type = STLINK_FLASH_TYPE_L4, + .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 52.2, page 2049) + .flash_pagesize = 0x1000, // 4k, section 3.3, pg 97 + .sram_size = 0xa0000, // 192k (SRAM1) + 64k SRAM2 + 384k SRAM3 = 640k, or 0xA0000 + .bootrom_base = 0x1fff0000, // 3.3.1, pg 99 + .bootrom_size = 0x7000 // 28k (per bank), same source as base (pg 99) + }, + { + // STLINK_CHIPID_STM32_L41X + // From RM0394 Rev 4 and DS12469 Rev 5 + .chip_id = STLINK_CHIPID_STM32_L41X, + .description = "L41x", + .flash_type = STLINK_FLASH_TYPE_L4, + .flash_size_reg = 0x1fff75e0, // "Flash size data register" (RM0394, sec 47.2, page 1586) + .flash_pagesize = 0x800, // 2k (DS12469, sec 3.4, page 17) + // SRAM1 is 32k at 0x20000000 + // SRAM2 is 8k at 0x10000000 and 0x20008000 (DS12469, sec 3.5, page 18) + .sram_size = 0xa000, // 40k (DS12469, sec 3.5, page 18) + .bootrom_base = 0x1fff0000, // System Memory (RM0394, sec 3.3.1, table 8) + .bootrom_size = 0x7000 // 28k, same source as base + }, + { + // STLINK_CHIPID_STM32_L43X + // From RM0392. + .chip_id = STLINK_CHIPID_STM32_L43X, + .description = "L43x/L44x", + .flash_type = STLINK_FLASH_TYPE_L4, + .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 43.2, page 1410) + .flash_pagesize = 0x800, // 2k (sec 3.2, page 74; also appears in sec 3.3.1 + // and tables 7-8 on pages 75-76) + // SRAM1 is "up to" 64k in the standard Cortex-M memory map; + // SRAM2 is 16k mapped at 0x10000000 (sec 2.3, page 73 for + // sizes; table 2, page 74 for SRAM2 location) + .sram_size = 0xc000, + .bootrom_base = 0x1fff0000, // Tables 4-6, pages 80-81 (Bank 1 system memory) + .bootrom_size = 0x7000, // 28k (per bank), same source as base + .option_base = STM32_L4_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STLINK_CHIPID_STM32_L496X + // Support based on en.DM00083560.pdf (RM0351) document rev 5. + .chip_id = STLINK_CHIPID_STM32_L496X, + .description = "L496x/L4A6x", + .flash_type = STLINK_FLASH_TYPE_L4, + .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 49.2, page 1809) + .flash_pagesize = 0x800, // Page erase (2 Kbyte) (sec 3.2, page 93) + // SRAM1 is 256k at 0x20000000 + // SRAM2 is 64k at 0x20040000 (sec 2.2.1, fig 2, page 74) + .sram_size = 0x40000, // Embedded SRAM (sec 2.4, page 84) + .bootrom_base = 0x1fff0000, // System Memory (Bank 1) (sec 3.3.1) + .bootrom_size = 0x7000, // 28k (per bank), same source as base + .option_base = STM32_L4_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STLINK_CHIPID_STM32_L46X + // From RM0394 (updated version of RM0392?). + .chip_id = STLINK_CHIPID_STM32_L46X, + .description = "L45x/46x", + .flash_type = STLINK_FLASH_TYPE_L4, + .flash_size_reg = 0x1fff75e0, // "Flash size data register" (sec 45.2, page 1463) + .flash_pagesize = 0x800, // 2k (sec 3.2, page 73; also appears in sec 3.3.1 + // and tables 7 on pages 73-74) + // SRAM1 is 128k at 0x20000000; + // SRAM2 is 32k mapped at 0x10000000 (sec 2.4.2, table 3-4, page 68, also fig 2 on page 63) + .sram_size = 0x20000, + .bootrom_base = 0x1fff0000, // Tables 6, pages 71-72 (Bank 1 system memory, also fig 2 on page 63) + .bootrom_size = 0x7000 // 28k (per bank), same source as base + }, + { + // STM32L011 + .chip_id = STLINK_CHIPID_STM32_L011, + .description = "L011", + .flash_type = STLINK_FLASH_TYPE_L0, + .flash_size_reg = 0x1ff8007c, + .flash_pagesize = 0x80, + .sram_size = 0x2000, + .bootrom_base = 0x1ff00000, + .bootrom_size = 0x2000 + }, + { + // STM32G030/031/041 (from RM0454 & RM0444) + .chip_id = STLINK_CHIPID_STM32_G0_CAT1, + .description = "G030/G031/G041", + .flash_type = STLINK_FLASH_TYPE_G0, + .flash_size_reg = 0x1FFF75E0, // Section 38.2 + .flash_pagesize = 0x800, // 2k (sec 3.2) + .sram_size = 0x2000, // 8k (sec 2.3) + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x2000, // 8k (sec 2.2.2 table 3) + .option_base = STM32_G0_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32G071/081 (from RM0444) + .chip_id = STLINK_CHIPID_STM32_G0_CAT2, + .description = "G070/G071/G081", + .flash_type = STLINK_FLASH_TYPE_G0, + .flash_size_reg = 0x1FFF75E0, // Section 38.2 + .flash_pagesize = 0x800, // 2k (sec 3.2) + .sram_size = 0x9000, // 36k (sec 2.3) + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7000, // 28k (sec 2.2.2 table 2) + .option_base = STM32_G0_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32G431/441 (from RM0440) + .chip_id = STLINK_CHIPID_STM32_G4_CAT2, + .description = "G4 Category-2", + .flash_type = STLINK_FLASH_TYPE_G4, + .flash_size_reg = 0x1FFF75E0, // Section 47.2 + .flash_pagesize = 0x800, // 2k (sec 3.3.1) + // SRAM1 is 16k at 0x20000000 + // SRAM2 is 6k at 0x20014000 + // SRAM3/CCM is 10k at 0x10000000, aliased at 0x20018000 + .sram_size = 0x8000, // 32k (sec 2.4) + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7000, // 28k (table 2) + .option_base = STM32_G4_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32G471/473/474/483/484 (from RM0440) + .chip_id = STLINK_CHIPID_STM32_G4_CAT3, + .description = "G4 Category-3", + .flash_type = STLINK_FLASH_TYPE_G4, + .has_dual_bank = true, + .flash_size_reg = 0x1FFF75E0, // Section 47.2 + .flash_pagesize = 0x800, // 2k (sec 3.3.1) + // SRAM1 is 80k at 0x20000000 + // SRAM2 is 16k at 0x20014000 + // SRAM3/CCM is 32k at 0x10000000, aliased at 0x20018000 + .sram_size = 0x18000, // 128k (sec 2.4) + .bootrom_base = 0x1fff0000, + .bootrom_size = 0x7000, // 28k (table 2) + .option_base = STM32_G4_OPTION_BYTES_BASE, + .option_size = 4, + }, + { + // STM32WB55 (from RM0434) + .chip_id = STLINK_CHIPID_STM32_WB55, + .description = "WB55", + .flash_type = STLINK_FLASH_TYPE_WB, + .flash_size_reg = 0x1FFF75E0, + .flash_pagesize = 0x1000, // 4k + .sram_size = 0x40000, + .bootrom_base = 0x1fff0000, // see the memory map + .bootrom_size = 0x7000 + }, + { + // unknown + .chip_id = STLINK_CHIPID_UNKNOWN, + .description = "unknown device", + .flash_type = STLINK_FLASH_TYPE_UNKNOWN, + .flash_size_reg = 0x0, + .flash_pagesize = 0x0, + .sram_size = 0x0, + .bootrom_base = 0x0, + .bootrom_size = 0x0 + }, +}; + +const struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chipid) { + const struct stlink_chipid_params *params = NULL; + + for (size_t n = 0; n < STLINK_ARRAY_SIZE(devices); n++) + if (devices[n].chip_id == chipid) { + params = &devices[n]; + break; + } + + return(params); +} diff --git a/src/stlink-lib/chipid.h b/src/stlink-lib/chipid.h new file mode 100644 index 000000000..b591f0012 --- /dev/null +++ b/src/stlink-lib/chipid.h @@ -0,0 +1,90 @@ +#ifndef STLINK_CHIPID_H_ +#define STLINK_CHIPID_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Chip IDs are explained in the appropriate programming manual for the + * DBGMCU_IDCODE register (0xE0042000) + * stm32 chipids, only lower 12 bits... + */ +enum stlink_stm32_chipids { + STLINK_CHIPID_UNKNOWN = 0x000, + + STLINK_CHIPID_STM32_F1_MEDIUM = 0x410, + STLINK_CHIPID_STM32_F2 = 0x411, + STLINK_CHIPID_STM32_F1_LOW = 0x412, + STLINK_CHIPID_STM32_F4 = 0x413, + STLINK_CHIPID_STM32_F1_HIGH = 0x414, + STLINK_CHIPID_STM32_L4 = 0x415, + STLINK_CHIPID_STM32_L1_MEDIUM = 0x416, + STLINK_CHIPID_STM32_L0 = 0x417, + STLINK_CHIPID_STM32_F1_CONN = 0x418, + STLINK_CHIPID_STM32_F4_HD = 0x419, + STLINK_CHIPID_STM32_F1_VL_MEDIUM_LOW = 0x420, + STLINK_CHIPID_STM32_F446 = 0x421, + STLINK_CHIPID_STM32_F3 = 0x422, + STLINK_CHIPID_STM32_F4_LP = 0x423, + STLINK_CHIPID_STM32_L0_CAT2 = 0x425, + STLINK_CHIPID_STM32_L1_MEDIUM_PLUS = 0x427, /* assigned to some L1 "Medium-plus" chips */ + STLINK_CHIPID_STM32_F1_VL_HIGH = 0x428, + STLINK_CHIPID_STM32_L1_CAT2 = 0x429, + STLINK_CHIPID_STM32_F1_XL = 0x430, + STLINK_CHIPID_STM32_F411RE = 0x431, + STLINK_CHIPID_STM32_F37x = 0x432, + STLINK_CHIPID_STM32_F4_DE = 0x433, + STLINK_CHIPID_STM32_F4_DSI = 0x434, + STLINK_CHIPID_STM32_L43X = 0x435, /* covers STM32L43xxx and STM32L44xxx devices */ + STLINK_CHIPID_STM32_L496X = 0x461, /* covers STM32L496xx and STM32L4A6xx devices */ + STLINK_CHIPID_STM32_L46X = 0x462, /* covers STM32L45xxx and STM32L46xxx devices */ + STLINK_CHIPID_STM32_L41X = 0x464, /* covers STM32L41xxx and STM32L42xxx devices */ + STLINK_CHIPID_STM32_L1_HIGH = 0x436, /* assigned to some L1 "Medium-Plus" and "High" chips */ + STLINK_CHIPID_STM32_L152_RE = 0x437, + STLINK_CHIPID_STM32_F334 = 0x438, + STLINK_CHIPID_STM32_F3_SMALL = 0x439, + STLINK_CHIPID_STM32_F0 = 0x440, + STLINK_CHIPID_STM32_F412 = 0x441, + STLINK_CHIPID_STM32_F09X = 0x442, + STLINK_CHIPID_STM32_F0_SMALL = 0x444, + STLINK_CHIPID_STM32_F04 = 0x445, + STLINK_CHIPID_STM32_F303_HIGH = 0x446, + STLINK_CHIPID_STM32_L0_CAT5 = 0x447, + STLINK_CHIPID_STM32_F0_CAN = 0x448, + STLINK_CHIPID_STM32_F7 = 0x449, /* ID found on the NucleoF746ZG board */ + STLINK_CHIPID_STM32_F7XXXX = 0x451, + STLINK_CHIPID_STM32_F72XXX = 0x452, /* ID found on the NucleoF722ZE board */ + STLINK_CHIPID_STM32_L011 = 0x457, + STLINK_CHIPID_STM32_F410 = 0x458, + STLINK_CHIPID_STM32_G0_CAT2 = 0x460, /* G070/G071/081 */ + STLINK_CHIPID_STM32_F413 = 0x463, + STLINK_CHIPID_STM32_G0_CAT1 = 0x466, /* G030/G031/041 */ + STLINK_CHIPID_STM32_G4_CAT2 = 0x468, /* See: RM 0440 s46.6.1 "MCU device ID code" */ + STLINK_CHIPID_STM32_G4_CAT3 = 0x469, + STLINK_CHIPID_STM32_L4RX = 0x470, /* ID found on the STM32L4R9I-DISCO board */ + STLINK_CHIPID_STM32_WB55 = 0x495 +}; + +/** Chipid parameters */ +struct stlink_chipid_params { + uint32_t chip_id; + char *description; + enum stlink_flash_type flash_type; + bool has_dual_bank; + uint32_t flash_size_reg; + uint32_t flash_pagesize; + uint32_t sram_size; + uint32_t bootrom_base; + uint32_t bootrom_size; + uint32_t option_base; + uint32_t option_size; +}; + +const struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chipid); + +#ifdef __cplusplus +} +#endif + +#endif // STLINK_CHIPID_H_ diff --git a/include/stlink/commands.h b/src/stlink-lib/commands.h similarity index 97% rename from include/stlink/commands.h rename to src/stlink-lib/commands.h index a6830ff26..0925e8e67 100644 --- a/include/stlink/commands.h +++ b/src/stlink-lib/commands.h @@ -33,4 +33,4 @@ enum stlink_debug_commands { STLINK_DEBUG_ENTER_SWD = 0xa3 }; -#endif /* STLINK_COMMANDS_H_ */ +#endif // STLINK_COMMANDS_H_ diff --git a/src/stlink-lib/flash_loader.c b/src/stlink-lib/flash_loader.c new file mode 100644 index 000000000..71601e3da --- /dev/null +++ b/src/stlink-lib/flash_loader.c @@ -0,0 +1,386 @@ +#include +#include +#include + +#include +#include "flash_loader.h" + +#define FLASH_REGS_BANK2_OFS 0x40 +#define FLASH_BANK2_START_ADDR 0x08080000 + +/* DO NOT MODIFY SOURCECODE DIRECTLY, EDIT ASSEMBLY FILES INSTEAD */ + +/* flashloaders/stm32f0.s -- compiled with thumb2 */ +static const uint8_t loader_code_stm32vl[] = { + 0x16, 0x4f, 0x3c, 0x68, + 0x16, 0x4f, 0x3e, 0x68, + 0x36, 0x19, 0x16, 0x4f, + 0x3d, 0x68, 0x2d, 0x19, + 0x4f, 0xf0, 0x01, 0x07, + 0x33, 0x68, 0x3b, 0x43, + 0x33, 0x60, 0x03, 0x88, + 0x0b, 0x80, 0x4f, 0xf0, + 0x02, 0x07, 0xc0, 0x19, + 0xc9, 0x19, 0x4f, 0xf0, + 0x01, 0x07, 0x2b, 0x68, + 0x3b, 0x42, 0xfa, 0xd0, + 0x4f, 0xf0, 0x04, 0x07, + 0x3b, 0x42, 0x04, 0xd1, + 0x4f, 0xf0, 0x01, 0x07, + 0xd2, 0x1b, 0x00, 0x2a, + 0xe6, 0xd1, 0x4f, 0xf0, + 0x01, 0x07, 0x33, 0x68, + 0xbb, 0x43, 0x33, 0x60, + 0x00, 0xbe, 0x00, 0xbf, + 0x00, 0x20, 0x02, 0x40, + 0x10, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x20, + 0x54, 0x00, 0x00, 0x20, + 0x58, 0x00, 0x00, 0x20 +}; + +/* flashloaders/stm32f0.s -- thumb1 only, same sequence as for STM32VL, bank ignored */ +static const uint8_t loader_code_stm32f0[] = { + 0xc0, 0x46, 0xc0, 0x46, + 0x13, 0x4f, 0x3c, 0x68, + 0x13, 0x4f, 0x3e, 0x68, + 0x36, 0x19, 0x13, 0x4f, + 0x3d, 0x68, 0x2d, 0x19, + 0x12, 0x4f, 0x33, 0x68, + 0x3b, 0x43, 0x33, 0x60, + 0x03, 0x88, 0x0b, 0x80, + 0x10, 0x4f, 0xc0, 0x19, + 0xc9, 0x19, 0x0e, 0x4f, + 0x2b, 0x68, 0x3b, 0x42, + 0xfb, 0xd0, 0x0e, 0x4f, + 0x3b, 0x42, 0x03, 0xd1, + 0x0a, 0x4f, 0xd2, 0x1b, + 0x00, 0x2a, 0xeb, 0xd1, + 0x08, 0x4f, 0x33, 0x68, + 0xbb, 0x43, 0x33, 0x60, + 0x00, 0xbe, 0xc0, 0x46, + 0x00, 0x20, 0x02, 0x40, + 0x10, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x20, + 0x4c, 0x00, 0x00, 0x20, + 0x50, 0x00, 0x00, 0x20, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00 +}; + +static const uint8_t loader_code_stm32l[] = { + // flashloaders/stm32lx.s + + 0x03, 0x68, 0x0b, 0x60, + 0x4f, 0xf0, 0x04, 0x07, + 0x38, 0x44, 0x39, 0x44, + 0x4f, 0xf0, 0x01, 0x07, + 0xd2, 0x1b, 0x00, 0x2a, + 0xf4, 0xd1, 0x00, 0xbe, +}; + +static const uint8_t loader_code_stm32f4[] = { + // flashloaders/stm32f4.s + + 0xdf, 0xf8, 0x28, 0xc0, + 0xdf, 0xf8, 0x28, 0xa0, + 0xe2, 0x44, 0x03, 0x68, + 0x0b, 0x60, 0x00, 0xf1, + 0x04, 0x00, 0x01, 0xf1, + 0x04, 0x01, 0xba, 0xf8, + 0x00, 0x30, 0x13, 0xf0, + 0x01, 0x0f, 0xfa, 0xd0, + 0xa2, 0xf1, 0x01, 0x02, + 0x00, 0x2a, 0xf0, 0xd1, + 0x00, 0xbe, 0x00, 0xbf, + 0x00, 0x3c, 0x02, 0x40, + 0x0e, 0x00, 0x00, 0x00 +}; + +static const uint8_t loader_code_stm32f4_lv[] = { + // flashloaders/stm32f4lv.s + 0xdf, 0xf8, 0x2c, 0xc0, + 0xdf, 0xf8, 0x2c, 0xa0, + 0xe2, 0x44, 0x4f, 0xea, + 0x82, 0x02, 0x03, 0x78, + 0x0b, 0x70, 0x00, 0xf1, + 0x01, 0x00, 0x01, 0xf1, + 0x01, 0x01, 0xba, 0xf8, + 0x00, 0x30, 0x13, 0xf0, + 0x01, 0x0f, 0xfa, 0xd0, + 0xa2, 0xf1, 0x01, 0x02, + 0x00, 0x2a, 0xf0, 0xd1, + 0x00, 0xbe, 0x00, 0xbf, + 0x00, 0x3c, 0x02, 0x40, + 0x0e, 0x00, 0x00, 0x00 +}; + +static const uint8_t loader_code_stm32l4[] = { + // flashloaders/stm32l4.s + 0xdf, 0xf8, 0x2c, 0xc0, + 0xdf, 0xf8, 0x2c, 0xa0, + 0xe2, 0x44, 0x03, 0x68, + 0x44, 0x68, 0x0b, 0x60, + 0x4c, 0x60, 0x00, 0xf1, + 0x08, 0x00, 0x01, 0xf1, + 0x08, 0x01, 0xba, 0xf8, + 0x00, 0x30, 0x13, 0xf0, + 0x01, 0x0f, 0xfa, 0xd0, + 0xa2, 0xf1, 0x01, 0x02, + 0x00, 0x2a, 0xee, 0xd1, + 0x00, 0xbe, 0x00, 0xbf, + 0x00, 0x20, 0x02, 0x40, + 0x12, 0x00, 0x00, 0x00 +}; + +static const uint8_t loader_code_stm32f7[] = { + // flashloaders/stm32f7.s + 0xdf, 0xf8, 0x2c, 0xc0, + 0xdf, 0xf8, 0x2c, 0xa0, + 0xe2, 0x44, 0x03, 0x68, + 0x0b, 0x60, 0x00, 0xf1, + 0x04, 0x00, 0x01, 0xf1, + 0x04, 0x01, 0xbf, 0xf3, + 0x4f, 0x8f, 0xba, 0xf8, + 0x00, 0x30, 0x13, 0xf0, + 0x01, 0x0f, 0xfa, 0xd0, + 0xa2, 0xf1, 0x01, 0x02, + 0x00, 0x2a, 0xee, 0xd1, + 0x00, 0xbe, 0x00, 0xbf, + 0x00, 0x3c, 0x02, 0x40, + 0x0e, 0x00, 0x00, 0x00 +}; + +static const uint8_t loader_code_stm32f7_lv[] = { + // flashloaders/stm32f7lv.s + 0xdf, 0xf8, 0x30, 0xc0, + 0xdf, 0xf8, 0x30, 0xa0, + 0xe2, 0x44, 0x4f, 0xea, + 0x82, 0x02, 0x03, 0x78, + 0x0b, 0x70, 0x00, 0xf1, + 0x01, 0x00, 0x01, 0xf1, + 0x01, 0x01, 0xbf, 0xf3, + 0x4f, 0x8f, 0xba, 0xf8, + 0x00, 0x30, 0x13, 0xf0, + 0x01, 0x0f, 0xfa, 0xd0, + 0xa2, 0xf1, 0x01, 0x02, + 0x00, 0x2a, 0xee, 0xd1, + 0x00, 0xbe, 0x00, 0xbf, + 0x00, 0x3c, 0x02, 0x40, + 0x0e, 0x00, 0x00, 0x00 +}; + + +int stlink_flash_loader_init(stlink_t *sl, flash_loader_t *fl) { + size_t size = 0; + + // allocate the loader in SRAM + if (stlink_flash_loader_write_to_sram(sl, &fl->loader_addr, &size) == -1) { + WLOG("Failed to write flash loader to sram!\n"); + return(-1); + } + + // allocate a one page buffer in SRAM right after loader + fl->buf_addr = fl->loader_addr + (uint32_t)size; + ILOG("Successfully loaded flash loader in sram\n"); + + return(0); +} + +static int loader_v_dependent_assignment(stlink_t *sl, + const uint8_t **loader_code, size_t *loader_size, + const uint8_t *high_v_loader, size_t high_v_loader_size, + const uint8_t *low_v_loader, size_t low_v_loader_size) { + int retval = 0; + + if ( sl->version.stlink_v == 1) { + printf("STLINK V1 cannot read voltage, defaulting to 32-bit writes\n"); + *loader_code = high_v_loader; + *loader_size = high_v_loader_size; + } else { + int voltage = stlink_target_voltage(sl); + + if (voltage == -1) { + retval = -1; + printf("Failed to read Target voltage\n"); + } else { + if (voltage > 2700) { + *loader_code = high_v_loader; + *loader_size = high_v_loader_size; + } else { + *loader_code = low_v_loader; + *loader_size = low_v_loader_size; + } + } + } + + return(retval); +} + +int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) { + const uint8_t* loader_code; + size_t loader_size; + + if (sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM || + sl->chip_id == STLINK_CHIPID_STM32_L1_CAT2 || + sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM_PLUS || + sl->chip_id == STLINK_CHIPID_STM32_L1_HIGH || + sl->chip_id == STLINK_CHIPID_STM32_L152_RE || + sl->chip_id == STLINK_CHIPID_STM32_L011 || + sl->chip_id == STLINK_CHIPID_STM32_L0 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || + sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2) { // STM32l + loader_code = loader_code_stm32l; + loader_size = sizeof(loader_code_stm32l); + } else if (sl->core_id == STM32VL_CORE_ID || + sl->chip_id == STLINK_CHIPID_STM32_F1_MEDIUM || + sl->chip_id == STLINK_CHIPID_STM32_F3 || + sl->chip_id == STLINK_CHIPID_STM32_F3_SMALL || + sl->chip_id == STLINK_CHIPID_STM32_F303_HIGH || + sl->chip_id == STLINK_CHIPID_STM32_F37x || + sl->chip_id == STLINK_CHIPID_STM32_F334) { + loader_code = loader_code_stm32vl; + loader_size = sizeof(loader_code_stm32vl); + } else if (sl->chip_id == STLINK_CHIPID_STM32_F2 || + sl->chip_id == STLINK_CHIPID_STM32_F4 || + sl->chip_id == STLINK_CHIPID_STM32_F4_DE || + sl->chip_id == STLINK_CHIPID_STM32_F4_LP || + sl->chip_id == STLINK_CHIPID_STM32_F4_HD || + sl->chip_id == STLINK_CHIPID_STM32_F4_DSI || + sl->chip_id == STLINK_CHIPID_STM32_F410 || + sl->chip_id == STLINK_CHIPID_STM32_F411RE || + sl->chip_id == STLINK_CHIPID_STM32_F412 || + sl->chip_id == STLINK_CHIPID_STM32_F413 || + sl->chip_id == STLINK_CHIPID_STM32_F446) { + int retval; + retval = loader_v_dependent_assignment(sl, + &loader_code, &loader_size, + loader_code_stm32f4, sizeof(loader_code_stm32f4), + loader_code_stm32f4_lv, sizeof(loader_code_stm32f4_lv)); + + if (retval == -1) { return(retval); } + } else if (sl->core_id == STM32F7_CORE_ID || + sl->chip_id == STLINK_CHIPID_STM32_F7 || + sl->chip_id == STLINK_CHIPID_STM32_F7XXXX || + sl->chip_id == STLINK_CHIPID_STM32_F72XXX) { + int retval; + retval = loader_v_dependent_assignment(sl, + &loader_code, &loader_size, + loader_code_stm32f7, sizeof(loader_code_stm32f7), + loader_code_stm32f7_lv, sizeof(loader_code_stm32f7_lv)); + + if (retval == -1) { return(retval); } + } else if (sl->chip_id == STLINK_CHIPID_STM32_F0 || + sl->chip_id == STLINK_CHIPID_STM32_F04 || + sl->chip_id == STLINK_CHIPID_STM32_F0_CAN || + sl->chip_id == STLINK_CHIPID_STM32_F0_SMALL || + sl->chip_id == STLINK_CHIPID_STM32_F09X) { + loader_code = loader_code_stm32f0; + loader_size = sizeof(loader_code_stm32f0); + } else if ((sl->chip_id == STLINK_CHIPID_STM32_L4) || + (sl->chip_id == STLINK_CHIPID_STM32_L41X) || + (sl->chip_id == STLINK_CHIPID_STM32_L43X) || + (sl->chip_id == STLINK_CHIPID_STM32_L46X) || + (sl->chip_id == STLINK_CHIPID_STM32_L4RX) || + (sl->chip_id == STLINK_CHIPID_STM32_L496X)) { + loader_code = loader_code_stm32l4; + loader_size = sizeof(loader_code_stm32l4); + } else { + ELOG("unknown coreid, not sure what flash loader to use, aborting! coreid: %x, chipid: %x\n", + sl->core_id, sl->chip_id); + return(-1); + } + + memcpy(sl->q_buf, loader_code, loader_size); + int ret = stlink_write_mem32(sl, sl->sram_base, loader_size); + + if (ret) { return(ret); } + + *addr = sl->sram_base; + *size = loader_size; + + return(0); // success +} + +int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size) { + struct stlink_reg rr; + int i = 0; + size_t count = 0; + uint32_t flash_base = 0; + + DLOG("Running flash loader, write address:%#x, size: %u\n", target, (unsigned int)size); + + // TODO: This can never return -1 + if (write_buffer_to_sram(sl, fl, buf, size) == -1) { + // IMPOSSIBLE! + ELOG("write_buffer_to_sram() == -1\n"); + return(-1); + } + + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || + (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + count = size / sizeof(uint16_t); + + if (size % sizeof(uint16_t)) { ++count; } + } else if (sl->flash_type == STLINK_FLASH_TYPE_F4 || + sl->flash_type == STLINK_FLASH_TYPE_L0) { + count = size / sizeof(uint32_t); + + if (size % sizeof(uint32_t)) { ++count; } + } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { + count = size / sizeof(uint64_t); + + if (size % sizeof(uint64_t)) { ++count; } + } + + if ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (target >= FLASH_BANK2_START_ADDR)) { + flash_base = FLASH_REGS_BANK2_OFS; + } + + /* Setup core */ + stlink_write_reg(sl, fl->buf_addr, 0); // source + stlink_write_reg(sl, target, 1); // target + stlink_write_reg(sl, (uint32_t)count, 2); // count + stlink_write_reg(sl, flash_base, 3); // flash register base + // only used on VL/F1_XL, but harmless for others + stlink_write_reg(sl, fl->loader_addr, 15); // pc register + + /* Run loader */ + stlink_run(sl); + +/* This piece of code used to try to spin for .1 second by waiting doing 10000 rounds of 10 µs. + * But because this usually runs on Unix-like OSes, the 10 µs get rounded up to the "tick" + * (actually almost two ticks) of the system. 1 ms. Thus, the ten thousand attempts, when + * "something goes wrong" that requires the error message "flash loader run error" would wait + * for something like 20 seconds before coming up with the error. + * By increasing the sleep-per-round to the same order-of-magnitude as the tick-rounding that + * the OS uses, the wait until the error message is reduced to the same order of magnitude + * as what was intended. -- REW. + */ +#define WAIT_ROUNDS 100 + + // wait until done (reaches breakpoint) + for (i = 0; i < WAIT_ROUNDS; i++) { + usleep(1000); + + if (stlink_is_core_halted(sl)) { break; } + } + + if (i >= WAIT_ROUNDS) { + ELOG("flash loader run error\n"); + return(-1); + } + + // check written byte count + stlink_read_reg(sl, 2, &rr); + + if (rr.r[2] != 0) { + ELOG("write error, count == %u\n", rr.r[2]); + return(-1); + } + + return(0); +} diff --git a/include/stlink/flash_loader.h b/src/stlink-lib/flash_loader.h similarity index 82% rename from include/stlink/flash_loader.h rename to src/stlink-lib/flash_loader.h index 5f4526114..29fd5b068 100644 --- a/include/stlink/flash_loader.h +++ b/src/stlink-lib/flash_loader.h @@ -1,8 +1,8 @@ /* - * File: stlink.h + * File: stlink.h * - * This should contain all the common top level stlink interfaces, regardless - * of how the backend does the work.... + * This should contain all the common top level stlink interfaces, + * regardless of how the backend does the work.... */ #ifndef STLINK_FLASH_LOADER_H_ #define STLINK_FLASH_LOADER_H_ @@ -24,4 +24,4 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe } #endif -#endif /* STLINK_FLASH_LOADER_H_ */ +#endif // STLINK_FLASH_LOADER_H_ diff --git a/src/libusb_settings.h b/src/stlink-lib/libusb_settings.h similarity index 53% rename from src/libusb_settings.h rename to src/stlink-lib/libusb_settings.h index c2e2df923..046c0b33d 100644 --- a/src/libusb_settings.h +++ b/src/stlink-lib/libusb_settings.h @@ -5,24 +5,24 @@ /* - libusb ver | LIBUSB_API_VERSION --------------+-------------------- - v1.0.13 | 0x01000100 - v1.0.14 | 0x010000FF - v1.0.15 | 0x01000101 - v1.0.16 | 0x01000102 - v1.0.17 | 0x01000102 - v1.0.18 | 0x01000102 - v1.0.19 | 0x01000103 - v1.0.20 | 0x01000104 - v1.0.21 | 0x01000105 - v1.0.22 | 0x01000106 - v1.0.23 | 0x01000107 - -*/ + libusb ver | LIBUSB_API_VERSION + -----------+-------------------- + v1.0.13 | 0x01000100 + v1.0.14 | 0x010000FF + v1.0.15 | 0x01000101 + v1.0.16 | 0x01000102 + v1.0.17 | 0x01000102 + v1.0.18 | 0x01000102 + v1.0.19 | 0x01000103 + v1.0.20 | 0x01000104 + v1.0.21 | 0x01000105 + v1.0.22 | 0x01000106 + v1.0.23 | 0x01000107 + + */ #if defined (__FreeBSD__) - #if !defined ( LIBUSBX_API_VERSION ) + #if !defined (LIBUSBX_API_VERSION) #define LIBUSBX_API_VERSION LIBUSB_API_VERSION #elif !defined (LIBUSB_API_VERSION) #error unsupported libusb version @@ -39,8 +39,8 @@ #define MINIMAL_API_VERSION 0x01000104 // v1.0.20 #endif -#if ( LIBUSB_API_VERSION < MINIMAL_API_VERSION ) +#if (LIBUSB_API_VERSION < MINIMAL_API_VERSION) #error unsupported libusb version #endif -#endif // STLINKUSB_H +#endif // LIBUSB_SETTINGS_H diff --git a/src/logging.c b/src/stlink-lib/logging.c similarity index 75% rename from src/logging.c rename to src/stlink-lib/logging.c index ad144f6a4..a5eef9e17 100644 --- a/src/logging.c +++ b/src/stlink-lib/logging.c @@ -1,7 +1,7 @@ /* - * UglyLogging. Slow, yet another wheel reinvented, but enough to make the - * rest of our code pretty enough. + * UglyLogging * + * Slow, yet another wheel reinvented, but enough to make the rest of our code pretty enough. */ #include #include @@ -15,23 +15,24 @@ static int max_level = UDEBUG; int ugly_init(int maximum_threshold) { max_level = maximum_threshold; - return 0; + return(0); } int ugly_log(int level, const char *tag, const char *format, ...) { if (level > max_level) { - return 0; + return(0); } - // Flush to maintain order of streams - fflush(stdout); + fflush(stdout); // flush to maintain order of streams va_list args; va_start(args, format); time_t mytt = time(NULL); struct tm *tt; tt = localtime(&mytt); - fprintf(stderr, "%d-%02d-%02dT%02d:%02d:%02d ", tt->tm_year + 1900, tt->tm_mon + 1, tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec); + fprintf(stderr, "%d-%02d-%02dT%02d:%02d:%02d ", tt->tm_year + 1900, tt->tm_mon + 1, + tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec); + switch (level) { case UDEBUG: fprintf(stderr, "DEBUG %s: ", tag); @@ -49,13 +50,13 @@ int ugly_log(int level, const char *tag, const char *format, ...) { fprintf(stderr, "%d %s: ", level, tag); break; } + vfprintf(stderr, format, args); fflush(stderr); va_end(args); - return 1; + return(1); } - /* * Log message levels. * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) @@ -63,15 +64,14 @@ int ugly_log(int level, const char *tag, const char *format, ...) { * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr -*/ -int ugly_libusb_log_level(enum ugly_loglevel v) -{ + */ +int ugly_libusb_log_level(enum ugly_loglevel v) { switch (v) { - case UDEBUG: return 4; - case UINFO: return 3; - case UWARN: return 2; - case UERROR: return 1; - }; + case UDEBUG: return(4); + case UINFO: return(3); + case UWARN: return(2); + case UERROR: return(1); + } - return 2; + return(2); } diff --git a/src/logging.h b/src/stlink-lib/logging.h similarity index 71% rename from src/logging.h rename to src/stlink-lib/logging.h index 1083b2c55..78562b0d9 100644 --- a/src/logging.h +++ b/src/stlink-lib/logging.h @@ -3,9 +3,9 @@ */ #ifndef UGLYLOGGING_H -#define UGLYLOGGING_H +#define UGLYLOGGING_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -21,11 +21,11 @@ int ugly_log(int level, const char *tag, const char *format, ...); int ugly_libusb_log_level(enum ugly_loglevel v); #define UGLY_LOG_FILE (strstr(__FILE__, "/") != NULL ? \ - strrchr(__FILE__, '/') + 1 : strstr(__FILE__, "\\") != NULL ? \ - strrchr(__FILE__, '\\') + 1 : __FILE__) + strrchr(__FILE__, '/') + 1 : strstr(__FILE__, "\\") != NULL ? \ + strrchr(__FILE__, '\\') + 1 : __FILE__) -/** @todo we need to write this in a more generic way, for now this should compile - on visual studio (See http://stackoverflow.com/a/8673872/1836746) */ +// TODO: we need to write this in a more generic way, for now this should compile +// on visual studio (See http://stackoverflow.com/a/8673872/1836746) #define DLOG_HELPER(format, ...) ugly_log(UDEBUG, UGLY_LOG_FILE, format, __VA_ARGS__) #define DLOG(...) DLOG_HELPER(__VA_ARGS__, "") #define ILOG_HELPER(format, ...) ugly_log(UINFO, UGLY_LOG_FILE, format, __VA_ARGS__) @@ -35,9 +35,8 @@ int ugly_libusb_log_level(enum ugly_loglevel v); #define ELOG_HELPER(format, ...) ugly_log(UERROR, UGLY_LOG_FILE, format, __VA_ARGS__) #define ELOG(...) ELOG_HELPER(__VA_ARGS__, "") -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* UGLYLOGGING_H */ - +#endif // UGLYLOGGING_H diff --git a/src/stlink-lib/md5.c b/src/stlink-lib/md5.c new file mode 100755 index 000000000..4c353bfd6 --- /dev/null +++ b/src/stlink-lib/md5.c @@ -0,0 +1,279 @@ +/* + * WjCryptLib_Md5 (https://github.com/WaterJuice/WjCryptLib) + * Implementation of MD5 hash function. Originally written by Alexander Peslyak. + * Modified by WaterJuice retaining Public Domain license. + * This is free and unencumbered software released into the public domain - June 2013 - waterjuice.org + */ + +#include + +#include "md5.h" + +/* INTERNAL FUNCTIONS */ + +/* F, G, H, I + * + * The basic MD5 functions. + * F and G are optimised compared to their RFC 1321 definitions for architectures + * that lack an AND-NOT instruction, just like in Colin Plumb's implementation. + */ +#define F( x, y, z ) ((z) ^ ((x) & ((y) ^ (z)))) +#define G( x, y, z ) ((y) ^ ((z) & ((x) ^ (y)))) +#define H( x, y, z ) ((x) ^ (y) ^ (z)) +#define I( x, y, z ) ((y) ^ ((x) | ~(z))) + +/* STEP: The MD5 transformation for all four rounds. */ +#define STEP( f, a, b, c, d, x, t, s ) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* TransformFunction + * This processes one or more 64-byte data blocks, but does NOT update the bit counters. + * There are no alignment requirements. + */ +static void* TransformFunction(Md5Context* ctx, void const* data, uintmax_t size) { + uint8_t* ptr; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t saved_a; + uint32_t saved_b; + uint32_t saved_c; + uint32_t saved_d; + + #define GET(n) (ctx->block[(n)]) + #define SET(n) (ctx->block[(n)] = ((uint32_t)ptr[(n) * 4 + 0] << 0) | \ + ((uint32_t)ptr[(n) * 4 + 1] << 8) | \ + ((uint32_t)ptr[(n) * 4 + 2] << 16) | \ + ((uint32_t)ptr[(n) * 4 + 3] << 24)) + + ptr = (uint8_t*)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + + // Round 1 + STEP( F, a, b, c, d, SET(0), 0xd76aa478, 7 ) + STEP( F, d, a, b, c, SET(1), 0xe8c7b756, 12 ) + STEP( F, c, d, a, b, SET(2), 0x242070db, 17 ) + STEP( F, b, c, d, a, SET(3), 0xc1bdceee, 22 ) + STEP( F, a, b, c, d, SET(4), 0xf57c0faf, 7 ) + STEP( F, d, a, b, c, SET(5), 0x4787c62a, 12 ) + STEP( F, c, d, a, b, SET(6), 0xa8304613, 17 ) + STEP( F, b, c, d, a, SET(7), 0xfd469501, 22 ) + STEP( F, a, b, c, d, SET(8 ), 0x698098d8, 7 ) + STEP( F, d, a, b, c, SET(9 ), 0x8b44f7af, 12 ) + STEP( F, c, d, a, b, SET(10 ), 0xffff5bb1, 17 ) + STEP( F, b, c, d, a, SET(11 ), 0x895cd7be, 22 ) + STEP( F, a, b, c, d, SET(12 ), 0x6b901122, 7 ) + STEP( F, d, a, b, c, SET(13 ), 0xfd987193, 12 ) + STEP( F, c, d, a, b, SET(14 ), 0xa679438e, 17 ) + STEP( F, b, c, d, a, SET(15 ), 0x49b40821, 22 ) + + // Round 2 + STEP( G, a, b, c, d, GET(1), 0xf61e2562, 5 ) + STEP( G, d, a, b, c, GET(6), 0xc040b340, 9 ) + STEP( G, c, d, a, b, GET(11), 0x265e5a51, 14 ) + STEP( G, b, c, d, a, GET(0), 0xe9b6c7aa, 20 ) + STEP( G, a, b, c, d, GET(5), 0xd62f105d, 5 ) + STEP( G, d, a, b, c, GET(10), 0x02441453, 9 ) + STEP( G, c, d, a, b, GET(15), 0xd8a1e681, 14 ) + STEP( G, b, c, d, a, GET(4), 0xe7d3fbc8, 20 ) + STEP( G, a, b, c, d, GET(9), 0x21e1cde6, 5 ) + STEP( G, d, a, b, c, GET(14), 0xc33707d6, 9 ) + STEP( G, c, d, a, b, GET(3), 0xf4d50d87, 14 ) + STEP( G, b, c, d, a, GET(8), 0x455a14ed, 20 ) + STEP( G, a, b, c, d, GET(13), 0xa9e3e905, 5 ) + STEP( G, d, a, b, c, GET(2), 0xfcefa3f8, 9 ) + STEP( G, c, d, a, b, GET(7), 0x676f02d9, 14 ) + STEP( G, b, c, d, a, GET(12), 0x8d2a4c8a, 20 ) + + // Round 3 + STEP( H, a, b, c, d, GET(5), 0xfffa3942, 4 ) + STEP( H, d, a, b, c, GET(8), 0x8771f681, 11 ) + STEP( H, c, d, a, b, GET(11), 0x6d9d6122, 16 ) + STEP( H, b, c, d, a, GET(14), 0xfde5380c, 23 ) + STEP( H, a, b, c, d, GET(1), 0xa4beea44, 4 ) + STEP( H, d, a, b, c, GET(4), 0x4bdecfa9, 11 ) + STEP( H, c, d, a, b, GET(7), 0xf6bb4b60, 16 ) + STEP( H, b, c, d, a, GET(10), 0xbebfbc70, 23 ) + STEP( H, a, b, c, d, GET(13), 0x289b7ec6, 4 ) + STEP( H, d, a, b, c, GET(0), 0xeaa127fa, 11 ) + STEP( H, c, d, a, b, GET(3), 0xd4ef3085, 16 ) + STEP( H, b, c, d, a, GET(6), 0x04881d05, 23 ) + STEP( H, a, b, c, d, GET(9), 0xd9d4d039, 4 ) + STEP( H, d, a, b, c, GET(12), 0xe6db99e5, 11 ) + STEP( H, c, d, a, b, GET(15), 0x1fa27cf8, 16 ) + STEP( H, b, c, d, a, GET(2), 0xc4ac5665, 23 ) + + // Round 4 + STEP( I, a, b, c, d, GET(0), 0xf4292244, 6 ) + STEP( I, d, a, b, c, GET(7), 0x432aff97, 10 ) + STEP( I, c, d, a, b, GET(14), 0xab9423a7, 15 ) + STEP( I, b, c, d, a, GET(5), 0xfc93a039, 21 ) + STEP( I, a, b, c, d, GET(12), 0x655b59c3, 6 ) + STEP( I, d, a, b, c, GET(3), 0x8f0ccc92, 10 ) + STEP( I, c, d, a, b, GET(10), 0xffeff47d, 15 ) + STEP( I, b, c, d, a, GET(1), 0x85845dd1, 21 ) + STEP( I, a, b, c, d, GET(8), 0x6fa87e4f, 6 ) + STEP( I, d, a, b, c, GET(15), 0xfe2ce6e0, 10 ) + STEP( I, c, d, a, b, GET(6), 0xa3014314, 15 ) + STEP( I, b, c, d, a, GET(13), 0x4e0811a1, 21 ) + STEP( I, a, b, c, d, GET(4), 0xf7537e82, 6 ) + STEP( I, d, a, b, c, GET(11), 0xbd3af235, 10 ) + STEP( I, c, d, a, b, GET(2), 0x2ad7d2bb, 15 ) + STEP( I, b, c, d, a, GET(9), 0xeb86d391, 21 ) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while ( size -= 64 ); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + #undef GET + #undef SET + + return(ptr); +} + +/* EXPORTED FUNCTIONS */ + +/* Md5Initialise + * Initialises an MD5 Context. + * Use this to initialise/reset a context. + */ +void Md5Initialise(Md5Context* Context /* [out] */) { + Context->a = 0x67452301; + Context->b = 0xefcdab89; + Context->c = 0x98badcfe; + Context->d = 0x10325476; + + Context->lo = 0; + Context->hi = 0; +} + +/* Md5Update + * Adds data to the MD5 context. + * This will process the data and update the internal state of the context. + * Keep on calling this function until all the data has been added. + * Then call Md5Finalise to calculate the hash. + */ +void Md5Update(Md5Context* Context /* [in out] */, void const* Buffer /* [in] */, uint32_t BufferSize /* [in] */) { + uint32_t saved_lo; + uint32_t used; + uint32_t free; + + saved_lo = Context->lo; + + if ((Context->lo = (saved_lo + BufferSize) & 0x1fffffff) < saved_lo) { + Context->hi++; + } + + Context->hi += (uint32_t)(BufferSize >> 29); + + used = saved_lo & 0x3f; + + if ( used ) { + free = 64 - used; + + if ( BufferSize < free ) { + memcpy( &Context->buffer[used], Buffer, BufferSize ); + return; + } + + memcpy( &Context->buffer[used], Buffer, free ); + Buffer = (uint8_t*)Buffer + free; + BufferSize -= free; + TransformFunction(Context, Context->buffer, 64); + } + + if ( BufferSize >= 64 ) { + Buffer = TransformFunction( Context, Buffer, BufferSize & ~(unsigned long)0x3f ); + BufferSize &= 0x3f; + } + + memcpy( Context->buffer, Buffer, BufferSize ); +} + +/* Md5Finalise + * Performs the final calculation of the hash and returns the digest + * (16 byte buffer containing 128bit hash). + * After calling this, Md5Initialised must be used to reuse the context. + */ +void Md5Finalise(Md5Context* Context /* [in out] */, MD5_HASH* Digest /* [in] */) { + uint32_t used; + uint32_t free; + + used = Context->lo & 0x3f; + + Context->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + memset( &Context->buffer[used], 0, free ); + TransformFunction( Context, Context->buffer, 64 ); + used = 0; + free = 64; + } + + memset( &Context->buffer[used], 0, free - 8 ); + + Context->lo <<= 3; + Context->buffer[56] = (uint8_t)(Context->lo); + Context->buffer[57] = (uint8_t)(Context->lo >> 8); + Context->buffer[58] = (uint8_t)(Context->lo >> 16); + Context->buffer[59] = (uint8_t)(Context->lo >> 24); + Context->buffer[60] = (uint8_t)(Context->hi); + Context->buffer[61] = (uint8_t)(Context->hi >> 8); + Context->buffer[62] = (uint8_t)(Context->hi >> 16); + Context->buffer[63] = (uint8_t)(Context->hi >> 24); + + TransformFunction( Context, Context->buffer, 64 ); + + Digest->bytes[0] = (uint8_t)(Context->a); + Digest->bytes[1] = (uint8_t)(Context->a >> 8); + Digest->bytes[2] = (uint8_t)(Context->a >> 16); + Digest->bytes[3] = (uint8_t)(Context->a >> 24); + Digest->bytes[4] = (uint8_t)(Context->b); + Digest->bytes[5] = (uint8_t)(Context->b >> 8); + Digest->bytes[6] = (uint8_t)(Context->b >> 16); + Digest->bytes[7] = (uint8_t)(Context->b >> 24); + Digest->bytes[8] = (uint8_t)(Context->c); + Digest->bytes[9] = (uint8_t)(Context->c >> 8); + Digest->bytes[10] = (uint8_t)(Context->c >> 16); + Digest->bytes[11] = (uint8_t)(Context->c >> 24); + Digest->bytes[12] = (uint8_t)(Context->d); + Digest->bytes[13] = (uint8_t)(Context->d >> 8); + Digest->bytes[14] = (uint8_t)(Context->d >> 16); + Digest->bytes[15] = (uint8_t)(Context->d >> 24); +} + +/* Md5Calculate + * Combines Md5Initialise, Md5Update, and Md5Finalise into one function. + * Calculates the MD5 hash of the buffer. + */ +void Md5Calculate(void const* Buffer /* [in] */, uint32_t BufferSize /* [in] */, MD5_HASH* Digest /* [in] */) { + Md5Context context; + + Md5Initialise( &context ); + Md5Update( &context, Buffer, BufferSize ); + Md5Finalise( &context, Digest ); +} diff --git a/src/stlink-lib/md5.h b/src/stlink-lib/md5.h new file mode 100755 index 000000000..a69d7fc6b --- /dev/null +++ b/src/stlink-lib/md5.h @@ -0,0 +1,63 @@ +/* + * WjCryptLib_Md5 (https://github.com/WaterJuice/WjCryptLib) + * Implementation of MD5 hash function. Originally written by Alexander Peslyak. + * Modified by WaterJuice retaining Public Domain license. + * This is free and unencumbered software released into the public domain - June 2013 - waterjuice.org + */ + +#pragma once + +#include +#include + +/* TYPES */ + +/* Md5Context + * This must be initialised using Md5Initialised. + * Do not modify the contents of this structure directly. + */ +typedef struct { + uint32_t lo; + uint32_t hi; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint8_t buffer[64]; + uint32_t block[16]; +} Md5Context; + +#define MD5_HASH_SIZE (128 / 8) + +typedef struct { + uint8_t bytes [MD5_HASH_SIZE]; +} MD5_HASH; + +/* PUBLIC FUNCTIONS */ + +/* Md5Initialise + * Initialises an MD5 Context. + * Use this to initialise/reset a context. + */ +void Md5Initialise(Md5Context* Context /* [out] */); + +/* Md5Update + * Adds data to the MD5 context. + * This will process the data and update the internal state of the context. + * Keep on calling this function until all the data has been added. + * Then call Md5Finalise to calculate the hash. + */ +void Md5Update(Md5Context* Context /* [in out] */, void const* Buffer /* [in] */, uint32_t BufferSize /* [in] */); + +/* Md5Finalise + * Performs the final calculation of the hash and returns the digest + * (16 byte buffer containing 128bit hash). + * After calling this, Md5Initialised must be used to reuse the context. + */ +void Md5Finalise(Md5Context* Context /* [in out] */, MD5_HASH* Digest /* [in] */); + +/* Md5Calculate + * Combines Md5Initialise, Md5Update, and Md5Finalise into one function. + * Calculates the MD5 hash of the buffer. + */ +void Md5Calculate(void const* Buffer /* [in] */, uint32_t BufferSize /* [in] */, MD5_HASH* Digest /* [in] */); diff --git a/src/stlink-lib/reg.h b/src/stlink-lib/reg.h new file mode 100644 index 000000000..dde77ef50 --- /dev/null +++ b/src/stlink-lib/reg.h @@ -0,0 +1,20 @@ +#ifndef STLINK_REG_H_ +#define STLINK_REG_H_ + +#define STLINK_REG_CM3_CPUID 0xE000ED00 +#define STLINK_REG_CM3_FP_CTRL 0xE0002000 +#define STLINK_REG_CM3_FP_COMP0 0xE0002008 + +/* Cortex™-M3 Technical Reference Manual */ +/* Debug Halting Control and Status Register */ +#define STLINK_REG_DHCSR 0xe000edf0 +#define STLINK_REG_DHCSR_DBGKEY 0xa05f0000 +#define STLINK_REG_DCRSR 0xe000edf4 +#define STLINK_REG_DCRDR 0xe000edf8 + +/* Application Interrupt and Reset Control Register */ +#define STLINK_REG_AIRCR 0xe000ed0c +#define STLINK_REG_AIRCR_VECTKEY 0x05fa0000 +#define STLINK_REG_AIRCR_SYSRESETREQ 0x00000004 + +#endif // STLINK_REG_H_ diff --git a/src/sg.c b/src/stlink-lib/sg.c similarity index 83% rename from src/sg.c rename to src/stlink-lib/sg.c index 798cda9ab..5cc27b1fe 100644 --- a/src/sg.c +++ b/src/stlink-lib/sg.c @@ -27,7 +27,7 @@ * www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf * * dt - Data Transfer (IN/OUT) - * CBW - Command Block Wrapper + * CBW - Command Block Wrapper * CSW - Command Status Wrapper * RFU - Reserved for Future Use * @@ -84,13 +84,14 @@ #include #include "logging.h" +#include "sg.h" #define STLINK_OK 0x80 #define STLINK_FALSE 0x81 static void clear_cdb(struct stlink_libsg *sl) { - for (size_t i = 0; i < sizeof (sl->cdb_cmd_blk); i++) - sl->cdb_cmd_blk[i] = 0; + for (size_t i = 0; i < sizeof(sl->cdb_cmd_blk); i++) { sl->cdb_cmd_blk[i] = 0; } + // set default sl->cdb_cmd_blk[0] = STLINK_DEBUG_COMMAND; sl->q_data_dir = Q_DATA_IN; @@ -115,46 +116,53 @@ static int get_usb_mass_storage_status(libusb_device_handle *handle, uint8_t end int transferred; int ret; int try = 0; + do { ret = libusb_bulk_transfer(handle, endpoint, (unsigned char *)&csw, sizeof(csw), - &transferred, SG_TIMEOUT_MSEC); - if (ret == LIBUSB_ERROR_PIPE) { - libusb_clear_halt(handle, endpoint); - } + &transferred, SG_TIMEOUT_MSEC); + + if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint); } + try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); + if (ret != LIBUSB_SUCCESS) { WLOG("%s: receiving failed: %d\n", __func__, ret); - return -1; + return(-1); } + if (transferred != sizeof(csw)) { WLOG("%s: received unexpected amount: %d\n", __func__, transferred); - return -1; + return(-1); } uint32_t rsig = read_uint32(csw, 0); uint32_t rtag = read_uint32(csw, 4); /* uint32_t residue = read_uint32(csw, 8); */ #define USB_CSW_SIGNATURE 0x53425355 // 'U' 'S' 'B' 'S' (reversed) + if (rsig != USB_CSW_SIGNATURE) { WLOG("status signature was invalid: %#x\n", rsig); - return -1; + return(-1); } + *tag = rtag; uint8_t rstatus = csw[12]; - return rstatus; + return(rstatus); } static int dump_CDB_command(uint8_t *cdb, uint8_t cdb_len) { char dbugblah[100]; char *dbugp = dbugblah; dbugp += sprintf(dbugp, "Sending CDB ["); + for (uint8_t i = 0; i < cdb_len; i++) { - dbugp += sprintf(dbugp, " %#02x", (unsigned int) cdb[i]); + dbugp += sprintf(dbugp, " %#02x", (unsigned int)cdb[i]); } + sprintf(dbugp, "]\n"); DLOG(dbugblah); - return 0; + return(0); } /** @@ -169,15 +177,14 @@ static int dump_CDB_command(uint8_t *cdb, uint8_t cdb_len) { * @return */ int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint_out, - uint8_t *cdb, uint8_t cdb_length, - uint8_t lun, uint8_t flags, uint32_t expected_rx_size) { + uint8_t *cdb, uint8_t cdb_length, + uint8_t lun, uint8_t flags, uint32_t expected_rx_size) { DLOG("Sending usb m-s cmd: cdblen:%d, rxsize=%d\n", cdb_length, expected_rx_size); dump_CDB_command(cdb, cdb_length); static uint32_t tag; - if (tag == 0) { - tag = 1; - } + + if (tag == 0) { tag = 1; } int try = 0; int ret = 0; @@ -192,14 +199,14 @@ int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint c_buf[i++] = 'C'; write_uint32(&c_buf[i], tag); uint32_t this_tag = tag++; - write_uint32(&c_buf[i+4], expected_rx_size); - i+= 8; + write_uint32(&c_buf[i + 4], expected_rx_size); + i += 8; c_buf[i++] = flags; c_buf[i++] = lun; c_buf[i++] = cdb_length; - // Now the actual CDB request + // now the actual CDB request assert(cdb_length <= CDB_SL); memcpy(&(c_buf[i]), cdb, cdb_length); @@ -208,19 +215,22 @@ int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint // send.... do { ret = libusb_bulk_transfer(handle, endpoint_out, c_buf, sending_length, - &real_transferred, SG_TIMEOUT_MSEC); + &real_transferred, SG_TIMEOUT_MSEC); + if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_out); } + try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); + if (ret != LIBUSB_SUCCESS) { WLOG("sending failed: %d\n", ret); - return -1; + return(-1); } - return this_tag; -} + return(this_tag); +} /** * Straight from stm8 stlink code... @@ -237,36 +247,44 @@ static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t cdb[0] = REQUEST_SENSE; cdb[4] = REQUEST_SENSE_LENGTH; uint32_t tag = send_usb_mass_storage_command(handle, endpoint_out, cdb, sizeof(cdb), 0, - LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH); + LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH); + if (tag == 0) { WLOG("refusing to send request sense with tag 0\n"); return; } + unsigned char sense[REQUEST_SENSE_LENGTH]; int transferred; int ret; int try = 0; + do { ret = libusb_bulk_transfer(handle, endpoint_in, sense, sizeof(sense), - &transferred, SG_TIMEOUT_MSEC); - if (ret == LIBUSB_ERROR_PIPE) { - libusb_clear_halt(handle, endpoint_in); - } + &transferred, SG_TIMEOUT_MSEC); + + if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_in); } + try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); + if (ret != LIBUSB_SUCCESS) { WLOG("receiving sense failed: %d\n", ret); return; } + if (transferred != sizeof(sense)) { WLOG("received unexpected amount of sense: %d != %d\n", transferred, sizeof(sense)); } + uint32_t received_tag; int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag); + if (status != 0) { WLOG("receiving sense failed with status: %02x\n", status); return; } + if (sense[0] != 0x70 && sense[0] != 0x71) { WLOG("No sense data\n"); } else { @@ -285,49 +303,55 @@ static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t * @return number of bytes actually sent, or -1 for failures. */ int send_usb_data_only(libusb_device_handle *handle, unsigned char endpoint_out, - unsigned char endpoint_in, unsigned char *cbuf, unsigned int length) { + unsigned char endpoint_in, unsigned char *cbuf, unsigned int length) { int ret; int real_transferred; int try = 0; + do { ret = libusb_bulk_transfer(handle, endpoint_out, cbuf, length, - &real_transferred, SG_TIMEOUT_MSEC); - if (ret == LIBUSB_ERROR_PIPE) { - libusb_clear_halt(handle, endpoint_out); - } + &real_transferred, SG_TIMEOUT_MSEC); + + if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_out); } + try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); + if (ret != LIBUSB_SUCCESS) { WLOG("sending failed: %d\n", ret); - return -1; + return(-1); } // now, swallow up the status, so that things behave nicely... uint32_t received_tag; // -ve is for my errors, 0 is good, +ve is libusb sense status bytes int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag); + if (status < 0) { WLOG("receiving status failed: %d\n", status); - return -1; + return(-1); } + if (status != 0) { WLOG("receiving status not passed :(: %02x\n", status); } + if (status == 1) { get_sense(handle, endpoint_in, endpoint_out); - return -1; + return(-1); } - return real_transferred; + return(real_transferred); } int stlink_q(stlink_t *sl) { struct stlink_libsg* sg = sl->backend_data; - //uint8_t cdb_len = 6; // FIXME varies!!! + // uint8_t cdb_len = 6; // FIXME varies!!! uint8_t cdb_len = 10; // FIXME varies!!! uint8_t lun = 0; // always zero... uint32_t tag = send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, - sg->cdb_cmd_blk, cdb_len, lun, LIBUSB_ENDPOINT_IN, sl->q_len); + sg->cdb_cmd_blk, cdb_len, lun, + LIBUSB_ENDPOINT_IN, sl->q_len); // now wait for our response... @@ -336,19 +360,20 @@ int stlink_q(stlink_t *sl) { int try = 0; int real_transferred; int ret; + if (rx_length > 0) { do { ret = libusb_bulk_transfer(sg->usb_handle, sg->ep_rep, sl->q_buf, rx_length, - &real_transferred, SG_TIMEOUT_MSEC); - if (ret == LIBUSB_ERROR_PIPE) { - libusb_clear_halt(sg->usb_handle, sg->ep_req); - } + &real_transferred, SG_TIMEOUT_MSEC); + + if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(sg->usb_handle, sg->ep_req); } + try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("Receiving failed: %d\n", ret); - return -1; + return(-1); } if (real_transferred != rx_length) { @@ -359,31 +384,36 @@ int stlink_q(stlink_t *sl) { uint32_t received_tag; // -ve is for my errors, 0 is good, +ve is libusb sense status bytes int status = get_usb_mass_storage_status(sg->usb_handle, sg->ep_rep, &received_tag); + if (status < 0) { WLOG("receiving status failed: %d\n", status); - return -1; + return(-1); } + if (status != 0) { WLOG("receiving status not passed :(: %02x\n", status); } + if (status == 1) { get_sense(sg->usb_handle, sg->ep_rep, sg->ep_req); - return -1; + return(-1); } + if (received_tag != tag) { WLOG("received tag %d but expected %d\n", received_tag, tag); - //return -1; + // return -1; } + if (rx_length > 0 && real_transferred != rx_length) { - return -1; + return(-1); } - return 0; + + return(0); } -// TODO thinking, cleanup +// TODO: thinking, cleanup void stlink_stat(stlink_t *stl, char *txt) { - if (stl->q_len <= 0) - return; + if (stl->q_len <= 0) { return; } stlink_print_data(stl); @@ -405,7 +435,7 @@ int _stlink_sg_version(stlink_t *stl) { sl->cdb_cmd_blk[0] = STLINK_GET_VERSION; stl->q_len = 6; sl->q_addr = 0; - return stlink_q(stl); + return(stlink_q(stl)); } // Get stlink mode: @@ -417,23 +447,23 @@ int _stlink_sg_current_mode(stlink_t *stl) { sl->cdb_cmd_blk[0] = STLINK_GET_CURRENT_MODE; stl->q_len = 2; sl->q_addr = 0; - if (stlink_q(stl)) - return -1; - return stl->q_buf[0]; + if (stlink_q(stl)) { return(-1); } + + return(stl->q_buf[0]); } -// Exit the mass mode and enter the swd debug mode. +// exit the mass mode and enter the swd debug mode. int _stlink_sg_enter_swd_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_SWD; sl->q_len = 0; // >0 -> aboard - return stlink_q(sl); + return(stlink_q(sl)); } -// Exit the mass mode and enter the jtag debug mode. +// exit the mass mode and enter the jtag debug mode. // (jtag is disabled in the discovery's stlink firmware) int _stlink_sg_enter_jtag_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; @@ -442,7 +472,7 @@ int _stlink_sg_enter_jtag_mode(stlink_t *sl) { sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG; sl->q_len = 0; - return stlink_q(sl); + return(stlink_q(sl)); } // XXX kernel driver performs reset, the device temporally disappears @@ -454,7 +484,7 @@ int _stlink_sg_exit_dfu_mode(stlink_t *sl) { sg->cdb_cmd_blk[0] = STLINK_DFU_COMMAND; sg->cdb_cmd_blk[1] = STLINK_DFU_EXIT; sl->q_len = 0; // ?? - return stlink_q(sl); + return(stlink_q(sl)); /* [135121.844564] sd 19:0:0:0: [sdb] Unhandled error code [135121.844569] sd 19:0:0:0: [sdb] Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK @@ -497,7 +527,7 @@ int _stlink_sg_exit_dfu_mode(stlink_t *sl) { [135131.678551] end_request: I/O error, dev sdb, sector 63872 ... [135131.853565] end_request: I/O error, dev sdb, sector 4096 - */ + */ } int _stlink_sg_core_id(stlink_t *sl) { @@ -508,73 +538,75 @@ int _stlink_sg_core_id(stlink_t *sl) { sl->q_len = 4; sg->q_addr = 0; ret = stlink_q(sl); - if (ret) - return ret; + + if (ret) { return(ret); } sl->core_id = read_uint32(sl->q_buf, 0); - return 0; + return(0); } -// Arm-core reset -> halted state. +// arm-core reset -> halted state. int _stlink_sg_reset(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_RESETSYS; sl->q_len = 2; sg->q_addr = 0; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } // Reset through AIRCR so NRST does not need to be connected if (stlink_write_debug32(sl, STLINK_REG_AIRCR, - STLINK_REG_AIRCR_VECTKEY | STLINK_REG_AIRCR_SYSRESETREQ)) - return -1; + STLINK_REG_AIRCR_VECTKEY | \ + STLINK_REG_AIRCR_SYSRESETREQ)) { + return(-1); + } stlink_stat(sl, "core reset"); - return 0; + return(0); } -// Arm-core reset -> halted state. +// arm-core reset -> halted state. int _stlink_sg_jtag_reset(stlink_t *sl, int value) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_JTAG_DRIVE_NRST; - sg->cdb_cmd_blk[2] = (value)?0:1; + sg->cdb_cmd_blk[2] = (value) ? 0 : 1; sl->q_len = 3; sg->q_addr = 2; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } stlink_stat(sl, "core reset"); - return 0; + return(0); } -// Arm-core status: halted or running. +// arm-core status: halted or running. int _stlink_sg_status(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS; sl->q_len = 2; sg->q_addr = 0; - return stlink_q(sl); + return(stlink_q(sl)); } -// Force the core into the debug mode -> halted state. +// force the core into the debug mode -> halted state. int _stlink_sg_force_debug(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG; sl->q_len = 2; sg->q_addr = 0; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } stlink_stat(sl, "force debug"); - return 0; + return(0); } -// Read all arm-core registers. +// read all arm-core registers. int _stlink_sg_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { struct stlink_libsg *sg = sl->backend_data; @@ -582,27 +614,28 @@ int _stlink_sg_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_READALLREGS; sl->q_len = 84; sg->q_addr = 0; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } stlink_print_data(sl); - // TODO - most of this should be re-extracted up.... + // TODO: most of this should be re-extracted up.... // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 for (int i = 0; i < 16; i++) { regp->r[i] = read_uint32(sl->q_buf, 4 * i); - if (sl->verbose > 1) - DLOG("r%2d = 0x%08x\n", i, regp->r[i]); + + if (sl->verbose > 1) { DLOG("r%2d = 0x%08x\n", i, regp->r[i]); } } + regp->xpsr = read_uint32(sl->q_buf, 64); regp->main_sp = read_uint32(sl->q_buf, 68); regp->process_sp = read_uint32(sl->q_buf, 72); regp->rw = read_uint32(sl->q_buf, 76); regp->rw2 = read_uint32(sl->q_buf, 80); - if (sl->verbose < 2) - return 0; + + if (sl->verbose < 2) { return(0); } DLOG("xpsr = 0x%08x\n", regp->xpsr); DLOG("main_sp = 0x%08x\n", regp->main_sp); @@ -610,10 +643,10 @@ int _stlink_sg_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { DLOG("rw = 0x%08x\n", regp->rw); DLOG("rw2 = 0x%08x\n", regp->rw2); - return 0; + return(0); } -// Read an arm-core register, the index must be in the range 0..20. +// read an arm-core register, the index must be in the range 0..20. // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 @@ -624,8 +657,8 @@ int _stlink_sg_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { sg->cdb_cmd_blk[2] = r_idx; sl->q_len = 4; sg->q_addr = 0; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83 @@ -646,19 +679,19 @@ int _stlink_sg_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { regp->process_sp = r; break; case 19: - regp->rw = r; //XXX ?(primask, basemask etc.) + regp->rw = r; // XXX ?(primask, basemask etc.) break; case 20: - regp->rw2 = r; //XXX ?(primask, basemask etc.) + regp->rw2 = r; // XXX ?(primask, basemask etc.) break; default: regp->r[r_idx] = r; } - return 0; + return(0); } -// Write an arm-core register. Index: +// write an arm-core register. Index: // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 @@ -672,16 +705,16 @@ int _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) { write_uint32(sg->cdb_cmd_blk + 3, reg); sl->q_len = 2; sg->q_addr = 0; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } stlink_stat(sl, "write reg"); - return 0; + return(0); } -// Write a register of the debug module of the core. +// write a register of the debug module of the core. // XXX ?(atomic writes) -// TODO test +// TODO: test void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_write_dreg ***\n"); @@ -697,38 +730,37 @@ void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) { stlink_stat(sl, "write debug reg"); } -// Force the core exit the debug mode. +// force the core exit the debug mode. int _stlink_sg_run(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE; sl->q_len = 2; sg->q_addr = 0; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } stlink_stat(sl, "run core"); - return 0; + return(0); } -// Step the arm-core. +// step the arm-core. int _stlink_sg_step(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_STEPCORE; sl->q_len = 2; sg->q_addr = 0; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } stlink_stat(sl, "step core"); - return 0; + return(0); } -// TODO test +// TODO: test and make delegate! // see Cortex-M3 Technical Reference Manual -// TODO make delegate! void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) { DLOG("\n*** stlink_set_hw_bp ***\n"); struct stlink_libsg *sg = sl->backend_data; @@ -746,8 +778,7 @@ void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) { stlink_stat(sl, "set flash breakpoint"); } -// TODO test -// TODO make delegate! +// TODO: test and make delegate! void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_clr_hw_bp ***\n"); @@ -760,7 +791,7 @@ void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) { stlink_stat(sl, "clear flash breakpoint"); } -// Read a "len" bytes to the sl->q_buf from the memory, max 6kB (6144 bytes) +// read a "len" bytes to the sl->q_buf from the memory, max 6kB (6144 bytes) int _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); @@ -777,14 +808,14 @@ int _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { // (broken residue issue) sl->q_len = len; sg->q_addr = addr; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } stlink_print_data(sl); - return 0; + return(0); } -// Write a "len" bytes from the sl->q_buf to the memory, max 64 Bytes. +// write a "len" bytes from the sl->q_buf to the memory, max 64 Bytes. int _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; int ret; @@ -798,21 +829,21 @@ int _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { // this sends the command... ret = send_usb_mass_storage_command(sg->usb_handle, - sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); - if (ret == -1) - return ret; + sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); + + if (ret == -1) { return(ret); } // This sends the data... ret = send_usb_data_only(sg->usb_handle, - sg->ep_req, sg->ep_rep, sl->q_buf, len); - if (ret == -1) - return ret; + sg->ep_req, sg->ep_rep, sl->q_buf, len); + + if (ret == -1) { return(ret); } stlink_print_data(sl); - return 0; + return(0); } -// Write a "len" bytes from the sl->q_buf to the memory, max Q_BUF_LEN bytes. +// write a "len" bytes from the sl->q_buf to the memory, max Q_BUF_LEN bytes. int _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; int ret; @@ -826,21 +857,21 @@ int _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { // this sends the command... ret = send_usb_mass_storage_command(sg->usb_handle, - sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); - if (ret == -1) - return ret; + sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); + + if (ret == -1) { return(ret); } // This sends the data... ret = send_usb_data_only(sg->usb_handle, - sg->ep_req, sg->ep_rep, sl->q_buf, len); - if (ret == -1) - return ret; + sg->ep_req, sg->ep_rep, sl->q_buf, len); + + if (ret == -1) { return(ret); } stlink_print_data(sl); - return 0; + return(0); } -// Write one DWORD data to memory +// write one DWORD data to memory int _stlink_sg_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); @@ -849,10 +880,10 @@ int _stlink_sg_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint32(sg->cdb_cmd_blk + 6, data); sl->q_len = 2; - return stlink_q(sl); + return(stlink_q(sl)); } -// Read one DWORD data from memory +// read one DWORD data from memory int _stlink_sg_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); @@ -860,24 +891,24 @@ int _stlink_sg_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { // 2-5: addr write_uint32(sg->cdb_cmd_blk + 2, addr); sl->q_len = 8; - if (stlink_q(sl)) - return -1; + + if (stlink_q(sl)) { return(-1); } *data = read_uint32(sl->q_buf, 4); - return 0; + return(0); } -// Exit the jtag or swd mode and enter the mass mode. +// exit the jtag or swd mode and enter the mass mode. int _stlink_sg_exit_debug_mode(stlink_t *stl) { if (stl) { struct stlink_libsg* sl = stl->backend_data; clear_cdb(sl); sl->cdb_cmd_blk[1] = STLINK_DEBUG_EXIT; stl->q_len = 0; // >0 -> aboard - return stlink_q(stl); + return(stlink_q(stl)); } - return 0; + return(0); } // 1) open a sg device, switch the stlink from dfu to mass mode @@ -905,35 +936,38 @@ static stlink_backend_t _stlink_sg_backend = { _stlink_sg_write_mem8, _stlink_sg_read_all_regs, _stlink_sg_read_reg, - NULL, /* read_all_unsupported_regs */ - NULL, /* read_unsupported_regs */ - NULL, /* write_unsupported_regs */ + NULL, // read_all_unsupported_regs + NULL, // read_unsupported_regs + NULL, // write_unsupported_regs _stlink_sg_write_reg, _stlink_sg_step, _stlink_sg_current_mode, _stlink_sg_force_debug, - NULL, /* target_voltage */ - NULL /* set_swdclk */ + NULL, // target_voltage + NULL // set_swdclk }; static stlink_t* stlink_open(const int verbose) { - stlink_t *sl = malloc(sizeof (stlink_t)); - struct stlink_libsg *slsg = malloc(sizeof (struct stlink_libsg)); + stlink_t *sl = malloc(sizeof(stlink_t)); + struct stlink_libsg *slsg = malloc(sizeof(struct stlink_libsg)); + if (sl == NULL || slsg == NULL) { WLOG("Couldn't malloc stlink and stlink_sg structures out of memory!\n"); - if (sl != NULL) - free(sl); - if (slsg != NULL) - free(slsg); - return NULL; + + if (sl != NULL) { free(sl); } + + if (slsg != NULL) { free(slsg); } + + return(NULL); } + memset(sl, 0, sizeof(stlink_t)); if (libusb_init(&(slsg->libusb_ctx))) { WLOG("failed to init libusb context, wrong version of libraries?\n"); free(sl); free(slsg); - return NULL; + return(NULL); } #if LIBUSB_API_VERSION < 0x01000106 @@ -943,32 +977,35 @@ static stlink_t* stlink_open(const int verbose) { #endif slsg->usb_handle = libusb_open_device_with_vid_pid(slsg->libusb_ctx, STLINK_USB_VID_ST, STLINK_USB_PID_STLINK); + if (slsg->usb_handle == NULL) { WLOG("Failed to find an stlink v1 by VID:PID\n"); libusb_close(slsg->usb_handle); libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); - return NULL; + return(NULL); } - // TODO - // Could read the interface config descriptor, and assert lots of the assumptions + // TODO: Could read the interface config descriptor, and assert lots of the assumptions // assumption: numInterfaces is always 1... if (libusb_kernel_driver_active(slsg->usb_handle, 0) == 1) { int r = libusb_detach_kernel_driver(slsg->usb_handle, 0); + if (r < 0) { WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-r)); libusb_close(slsg->usb_handle); libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); - return NULL; + return(NULL); } + DLOG("Kernel driver was successfully detached\n"); } int config; + if (libusb_get_configuration(slsg->usb_handle, &config)) { /* this may fail for a previous configured device */ WLOG("libusb_get_configuration()\n"); @@ -976,7 +1013,7 @@ static stlink_t* stlink_open(const int verbose) { libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); - return NULL; + return(NULL); } @@ -984,6 +1021,7 @@ static stlink_t* stlink_open(const int verbose) { if (config != 1) { WLOG("Your stlink got into a real weird configuration, trying to fix it!\n"); DLOG("setting new configuration (%d -> 1)\n", config); + if (libusb_set_configuration(slsg->usb_handle, 1)) { /* this may fail for a previous configured device */ WLOG("libusb_set_configuration() failed\n"); @@ -991,7 +1029,7 @@ static stlink_t* stlink_open(const int verbose) { libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); - return NULL; + return(NULL); } } @@ -1001,7 +1039,7 @@ static stlink_t* stlink_open(const int verbose) { libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); - return NULL; + return(NULL); } // assumption: endpoint config is fixed mang. really. @@ -1017,31 +1055,34 @@ static stlink_t* stlink_open(const int verbose) { sl->core_stat = TARGET_UNKNOWN; slsg->q_addr = 0; - return sl; + return(sl); } stlink_t* stlink_v1_open_inner(const int verbose) { ugly_init(verbose); stlink_t *sl = stlink_open(verbose); + if (sl == NULL) { ELOG("Could not open stlink device\n"); - return NULL; + return(NULL); } stlink_version(sl); + if ((sl->version.st_vid != STLINK_USB_VID_ST) || (sl->version.stlink_pid != STLINK_USB_PID_STLINK)) { ELOG("WTF? successfully opened, but unable to read version details. BROKEN!\n"); - return NULL; + return(NULL); } DLOG("Reading current mode...\n"); + switch (stlink_current_mode(sl)) { case STLINK_DEV_MASS_MODE: - return sl; + return(sl); case STLINK_DEV_DEBUG_MODE: // TODO go to mass? - return sl; + return(sl); default: ILOG("Current mode unusable, trying to get back to a useful state...\n"); break; @@ -1052,26 +1093,27 @@ stlink_t* stlink_v1_open_inner(const int verbose) { // re-query device info (and retest) stlink_version(sl); + if ((sl->version.st_vid != STLINK_USB_VID_ST) || (sl->version.stlink_pid != STLINK_USB_PID_STLINK)) { ELOG("WTF? successfully opened, but unable to read version details. BROKEN!\n"); - return NULL; + return(NULL); } - return sl; + return(sl); } stlink_t* stlink_v1_open(const int verbose, int reset) { stlink_t *sl = stlink_v1_open_inner(verbose); - if (sl == NULL) - return NULL; + + if (sl == NULL) { return(NULL); } // by now, it _must_ be fully open and in a useful mode.... stlink_enter_swd_mode(sl); - /* Now we are ready to read the parameters */ - if (reset) { - stlink_reset(sl); - } + + // now we are ready to read the parameters + if (reset) { stlink_reset(sl); } + stlink_load_device_params(sl); ILOG("Successfully opened a stlink v1 debugger\n"); - return sl; + return(sl); } diff --git a/src/stlink-lib/sg.h b/src/stlink-lib/sg.h new file mode 100644 index 000000000..f34b2e122 --- /dev/null +++ b/src/stlink-lib/sg.h @@ -0,0 +1,67 @@ +/* + * File: sg.h + * Author: karl + */ + +#ifndef STLINK_SG_H +#define STLINK_SG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Device access */ +#define RDWR 0 +#define RO 1 +#define SG_TIMEOUT_SEC 1 // actually 1 is about 2 sec +#define SG_TIMEOUT_MSEC 3 * 1000 + +// Each CDB can be a total of 6, 10, 12, or 16 bytes, later version of the SCSI standard +// also allow for variable-length CDBs (min. CDB is 6). The stlink needs max. 10 bytes. +#define CDB_6 6 +#define CDB_10 10 +#define CDB_12 12 +#define CDB_16 16 + +#define CDB_SL 10 + +/* Query data flow direction */ +#define Q_DATA_OUT 0 +#define Q_DATA_IN 1 + +// The SCSI Request Sense command is used to obtain sense data (error information) from +// a target device. (http://en.wikipedia.org/wiki/SCSI_Request_Sense_Command) +#define SENSE_BUF_LEN 32 + +struct stlink_libsg { + libusb_context* libusb_ctx; + libusb_device_handle *usb_handle; + unsigned ep_rep; + unsigned ep_req; + + int sg_fd; + int do_scsi_pt_err; + + unsigned char cdb_cmd_blk[CDB_SL]; + + int q_data_dir; // Q_DATA_IN, Q_DATA_OUT + // the start of the query data in the device memory space + uint32_t q_addr; + + // Sense (error information) data + // obsolete, this was fed to the scsi tools + unsigned char sense_buf[SENSE_BUF_LEN]; + + struct stlink_reg reg; +}; + +stlink_t* stlink_v1_open(const int verbose, int reset); + +#ifdef __cplusplus +} +#endif + +#endif // STLINK_SG_H diff --git a/src/usb.c b/src/stlink-lib/usb.c similarity index 75% rename from src/usb.c rename to src/stlink-lib/usb.c index a711749da..f9b4775f3 100644 --- a/src/usb.c +++ b/src/stlink-lib/usb.c @@ -3,22 +3,26 @@ #include #include #include + #if !defined(_MSC_VER) #include #endif + #include #include #include -#if defined(__MINGW32__) || defined(_MSC_VER) -#include +#if defined(_WIN32) +#include #endif + #include +#include "usb.h" -enum SCSI_Generic_Direction {SG_DXFER_TO_DEV=0, SG_DXFER_FROM_DEV=0x80}; +enum SCSI_Generic_Direction {SG_DXFER_TO_DEV = 0, SG_DXFER_FROM_DEV = 0x80}; static inline uint32_t le_to_h_u32(const uint8_t* buf) { - return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24); + return((uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24)); } static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, uint32_t khz) { @@ -29,15 +33,18 @@ static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, u bool match = true; for (i = 0; i < map_size; i++) { - if (!map[i]) continue; + if (!map[i]) { continue; } + last_valid_speed = i; + if (khz == map[i]) { speed_index = i; break; } else { int current_diff = khz - map[i]; - // Get abs value for comparison + // get abs value for comparison current_diff = (current_diff > 0) ? current_diff : -current_diff; + if ((current_diff < speed_diff) && khz >= map[i]) { speed_diff = current_diff; speed_index = i; @@ -46,72 +53,80 @@ static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, u } if (speed_index == -1) { - // This will only be here if we cannot match the slow speed. Use the slowest speed we support. + // This will only be here if we cannot match the slow speed. + // Use the slowest speed we support. speed_index = last_valid_speed; match = false; } else if (i == map_size) { match = false; } + if (!match) { ILOG("Unable to match requested speed %d kHz, using %d kHz\n", khz, map[speed_index]); } - return speed_index; + return(speed_index); } void _stlink_usb_close(stlink_t* sl) { - if (!sl) return; + if (!sl) { return; } struct stlink_libusb * const handle = sl->backend_data; - // Maybe we couldn't even get the usb device? + + // maybe we couldn't even get the usb device? if (handle != NULL) { - if (handle->usb_handle != NULL) libusb_close(handle->usb_handle); + if (handle->usb_handle != NULL) { libusb_close(handle->usb_handle); } + libusb_exit(handle->libusb_ctx); free(handle); } } ssize_t send_recv(struct stlink_libusb* handle, int terminate, - unsigned char* txbuf, size_t txsize, unsigned char* rxbuf, size_t rxsize) { - /* Note: txbuf and rxbuf can point to the same area */ + unsigned char* txbuf, size_t txsize, unsigned char* rxbuf, size_t rxsize) { + // Note: txbuf and rxbuf can point to the same area int res = 0; int t; - t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, txbuf, (int) txsize, &res, 3000); + t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, txbuf, (int)txsize, &res, 3000); + if (t) { printf("[!] send_recv send request failed: %s\n", libusb_error_name(t)); - return -1; + return(-1); } else if ((size_t)res != txsize) { printf("[!] send_recv send request wrote %u bytes (instead of %u).\n", - (unsigned int)res, (unsigned int)txsize); + (unsigned int)res, (unsigned int)txsize); } if (rxsize != 0) { - t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, rxbuf, (int) rxsize, &res, 3000); + t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, rxbuf, (int)rxsize, &res, 3000); + if (t) { printf("[!] send_recv read reply failed: %s\n", libusb_error_name(t)); - return -1; + return(-1); } } if ((handle->protocoll == 1) && terminate) { - // Read the SG reply + // read the SG reply unsigned char sg_buf[13]; t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, sg_buf, 13, &res, 3000); + if (t) { printf("[!] send_recv read storage failed: %s\n", libusb_error_name(t)); - return -1; + return(-1); } + // The STLink doesn't seem to evaluate the sequence number. handle->sg_transfer_idx++; } - return res; + return(res); } static inline int send_only(struct stlink_libusb* handle, int terminate, - unsigned char* txbuf, size_t txsize) { - return (int) send_recv(handle, terminate, txbuf, txsize, NULL, 0); + unsigned char* txbuf, size_t txsize) { + return((int)send_recv(handle, terminate, txbuf, txsize, NULL, 0)); } @@ -119,7 +134,8 @@ static int fill_command(stlink_t * sl, enum SCSI_Generic_Direction dir, uint32_t struct stlink_libusb * const slu = sl->backend_data; unsigned char* const cmd = sl->c_buf; int i = 0; - memset(cmd, 0, sizeof (sl->c_buf)); + memset(cmd, 0, sizeof(sl->c_buf)); + if (slu->protocoll == 1) { cmd[i++] = 'U'; cmd[i++] = 'S'; @@ -129,10 +145,11 @@ static int fill_command(stlink_t * sl, enum SCSI_Generic_Direction dir, uint32_t write_uint32(&cmd[i + 4], len); i += 8; cmd[i++] = (dir == SG_DXFER_FROM_DEV) ? 0x80 : 0; - cmd[i++] = 0; // Logical unit - cmd[i++] = 0xa; // Command length + cmd[i++] = 0; // logical unit + cmd[i++] = 0xa; // command length } - return i; + + return(i); } int _stlink_usb_version(stlink_t *sl) { @@ -146,9 +163,10 @@ int _stlink_usb_version(stlink_t *sl) { cmd[i++] = STLINK_GET_VERSION; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_GET_VERSION\n"); - return (int) size; + return((int)size); } /* STLINK-V3 requires a specific command */ @@ -158,13 +176,14 @@ int _stlink_usb_version(stlink_t *sl) { cmd[i++] = STLINK_APIV3_GET_VERSION_EX; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size != (ssize_t)rep_len) { printf("[!] send_recv STLINK_APIV3_GET_VERSION_EX\n"); - return (int) size; + return((int)size); } } - return 0; + return(0); } int32_t _stlink_usb_target_voltage(stlink_t *sl) { @@ -180,19 +199,20 @@ int32_t _stlink_usb_target_voltage(stlink_t *sl) { cmd[i++] = STLINK_GET_TARGET_VOLTAGE; size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_GET_TARGET_VOLTAGE\n"); - return -1; + return(-1); } else if (size != 8) { printf("[!] wrong length STLINK_GET_TARGET_VOLTAGE\n"); - return -1; + return(-1); } factor = (rdata[3] << 24) | (rdata[2] << 16) | (rdata[1] << 8) | (rdata[0] << 0); reading = (rdata[7] << 24) | (rdata[6] << 16) | (rdata[5] << 8) | (rdata[4] << 0); voltage = 2400 * reading / factor; - return voltage; + return(voltage); } int _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { @@ -207,13 +227,15 @@ int _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { cmd[i++] = STLINK_JTAG_READDEBUG_32BIT; write_uint32(&cmd[i], addr); size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_JTAG_READDEBUG_32BIT\n"); - return (int) size; + return((int)size); } + *data = read_uint32(rdata, 4); - return 0; + return(0); } int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { @@ -229,16 +251,17 @@ int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { write_uint32(&cmd[i], addr); write_uint32(&cmd[i + 4], data); size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_JTAG_WRITEDEBUG_32BIT\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } int _stlink_usb_get_rw_status(stlink_t *sl) { - if (sl->version.jtag_api == STLINK_JTAG_API_V1) return -1; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) { return(-1); } unsigned char* const rdata = sl->q_buf; struct stlink_libusb * const slu = sl->backend_data; @@ -248,6 +271,7 @@ int _stlink_usb_get_rw_status(stlink_t *sl) { i = fill_command(sl, SG_DXFER_FROM_DEV, 12); cmd[i++] = STLINK_DEBUG_COMMAND; + if (sl->version.flags & STLINK_F_HAS_GETLASTRWSTATUS2) { cmd[i++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS2; ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 12); @@ -255,9 +279,10 @@ int _stlink_usb_get_rw_status(stlink_t *sl) { cmd[i++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS; ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 2); } - if (ret < 0) return -1; - return 0; + if (ret < 0) { return(-1); } + + return(0); } int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { @@ -272,11 +297,14 @@ int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { write_uint32(&cmd[i], addr); write_uint16(&cmd[i + 4], len); ret = send_only(slu, 0, cmd, slu->cmd_len); - if (ret == -1) return ret; + + if (ret == -1) { return(ret); } + ret = send_only(slu, 0, data, len); - if (ret == -1) return ret; - return _stlink_usb_get_rw_status(sl); + if (ret == -1) { return(ret); } + + return(_stlink_usb_get_rw_status(sl)); } int _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { @@ -291,11 +319,14 @@ int _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { write_uint32(&cmd[i], addr); write_uint16(&cmd[i + 4], len); ret = send_only(slu, 0, cmd, slu->cmd_len); - if (ret == -1) return ret; + + if (ret == -1) { return(ret); } + ret = send_only(slu, 1, data, len); - if (ret == -1) return ret; - return 0; + if (ret == -1) { return(ret); } + + return(0); } @@ -309,12 +340,13 @@ int _stlink_usb_current_mode(stlink_t * sl) { cmd[i++] = STLINK_GET_CURRENT_MODE; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_GET_CURRENT_MODE\n"); - return -1; + return(-1); } - return sl->q_buf[0]; + return(sl->q_buf[0]); } int _stlink_usb_core_id(stlink_t * sl) { @@ -326,15 +358,18 @@ int _stlink_usb_core_id(stlink_t * sl) { int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) { cmd[i++] = STLINK_DEBUG_READCOREID; } else { cmd[i++] = STLINK_DEBUG_APIV2_READ_IDCODES; } + size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_READCOREID\n"); - return -1; + return(-1); } if (sl->version.jtag_api == STLINK_JTAG_API_V1) { @@ -342,16 +377,18 @@ int _stlink_usb_core_id(stlink_t * sl) { } else { sl->core_id = read_uint32(data, 4); } - return 0; + + return(0); } -int _stlink_usb_status_v2(stlink_t *sl) -{ + +int _stlink_usb_status_v2(stlink_t *sl) { int result; uint32_t status = 0; result = _stlink_usb_read_debug32(sl, DCB_DHCSR, &status); DLOG("core status: %08X\n", status); - if (result != 0) { + + if (result != 0) { sl->core_stat = TARGET_UNKNOWN; } else { if (status & S_HALT) { @@ -363,11 +400,11 @@ int _stlink_usb_status_v2(stlink_t *sl) } } - return result; + return(result); } int _stlink_usb_status(stlink_t * sl) { - if (sl->version.jtag_api != STLINK_JTAG_API_V1) return _stlink_usb_status_v2(sl); + if (sl->version.jtag_api != STLINK_JTAG_API_V1) { return(_stlink_usb_status_v2(sl)); } struct stlink_libusb * const slu = sl->backend_data; unsigned char* const data = sl->q_buf; @@ -379,21 +416,25 @@ int _stlink_usb_status(stlink_t * sl) { cmd[i++] = STLINK_DEBUG_COMMAND; cmd[i++] = STLINK_DEBUG_GETSTATUS; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_GETSTATUS\n"); - return (int) size; + return((int)size); } - sl->q_len = (int) size; + + sl->q_len = (int)size; + if (sl->q_len > 1) { - if (sl->q_buf[0] == STLINK_CORE_RUNNING) + if (sl->q_buf[0] == STLINK_CORE_RUNNING) { sl->core_stat = TARGET_RUNNING; - else if (sl->q_buf[0] == STLINK_CORE_HALTED) + } else if (sl->q_buf[0] == STLINK_CORE_HALTED) { sl->core_stat = TARGET_HALTED; - else + } else { sl->core_stat = TARGET_UNKNOWN; + } } - return 0; + return(0); } int _stlink_usb_force_debug(stlink_t *sl) { @@ -407,12 +448,13 @@ int _stlink_usb_force_debug(stlink_t *sl) { cmd[i++] = STLINK_DEBUG_COMMAND; cmd[i++] = STLINK_DEBUG_FORCEDEBUG; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_FORCEDEBUG\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } int _stlink_usb_enter_swd_mode(stlink_t * sl) { @@ -424,7 +466,7 @@ int _stlink_usb_enter_swd_mode(stlink_t * sl) { int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; - // Select correct API-Version for entering SWD mode: V1 API (0x20) or V2 API (0x30). + // select correct API-Version for entering SWD mode: V1 API (0x20) or V2 API (0x30). cmd[i++] = sl->version.jtag_api == STLINK_JTAG_API_V1 ? STLINK_DEBUG_APIV1_ENTER : STLINK_DEBUG_APIV2_ENTER; cmd[i++] = STLINK_DEBUG_ENTER_SWD; @@ -433,12 +475,13 @@ int _stlink_usb_enter_swd_mode(stlink_t * sl) { } else { size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); } + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_ENTER\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } int _stlink_usb_exit_dfu_mode(stlink_t* sl) { @@ -450,12 +493,13 @@ int _stlink_usb_exit_dfu_mode(stlink_t* sl) { cmd[i++] = STLINK_DFU_COMMAND; cmd[i++] = STLINK_DFU_EXIT; size = send_only(slu, 1, cmd, slu->cmd_len); + if (size == -1) { printf("[!] send_recv STLINK_DFU_EXIT\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } @@ -468,6 +512,7 @@ int _stlink_usb_reset(stlink_t * sl) { int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) { cmd[i++] = STLINK_DEBUG_APIV1_RESETSYS; } else { @@ -475,14 +520,15 @@ int _stlink_usb_reset(stlink_t * sl) { } size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_RESETSYS\n"); - return (int) size; + return((int)size); } - // Reset through AIRCR so that NRST does not need to be connected. - return stlink_write_debug32(sl, STLINK_REG_AIRCR, STLINK_REG_AIRCR_VECTKEY | - STLINK_REG_AIRCR_SYSRESETREQ); + // reset through AIRCR so that NRST does not need to be connected + return(stlink_write_debug32(sl, STLINK_REG_AIRCR, STLINK_REG_AIRCR_VECTKEY | + STLINK_REG_AIRCR_SYSRESETREQ)); } int _stlink_usb_jtag_reset(stlink_t * sl, int value) { @@ -497,12 +543,13 @@ int _stlink_usb_jtag_reset(stlink_t * sl, int value) { cmd[i++] = STLINK_JTAG_DRIVE_NRST; cmd[i++] = value; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_JTAG_DRIVE_NRST\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } @@ -517,12 +564,13 @@ int _stlink_usb_step(stlink_t* sl) { cmd[i++] = STLINK_DEBUG_COMMAND; cmd[i++] = STLINK_DEBUG_STEPCORE; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_STEPCORE\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } /** @@ -535,8 +583,8 @@ int _stlink_usb_run(stlink_t* sl) { int res; if (sl->version.jtag_api != STLINK_JTAG_API_V1) { - res = _stlink_usb_write_debug32(sl, DCB_DHCSR, DBGKEY|C_DEBUGEN); - return res; + res = _stlink_usb_write_debug32(sl, DCB_DHCSR, DBGKEY | C_DEBUGEN); + return(res); } @@ -549,15 +597,15 @@ int _stlink_usb_run(stlink_t* sl) { cmd[i++] = STLINK_DEBUG_COMMAND; cmd[i++] = STLINK_DEBUG_RUNCORE; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_RUNCORE\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } - int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) { struct stlink_libusb * const slu = sl->backend_data; unsigned char* const data = sl->q_buf; @@ -575,12 +623,13 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) { cmd[i++] = clk_divisor & 0xFF; cmd[i++] = (clk_divisor >> 8) & 0xFF; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { printf("[!] send_recv STLINK_DEBUG_APIV2_SWD_SET_FREQ\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } else if (sl->version.stlink_v == 3) { int speed_index; uint32_t map[STLINK_V3_MAX_FREQ_NB]; @@ -590,14 +639,17 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) { cmd[i++] = STLINK_APIV3_GET_COM_FREQ; cmd[i++] = 0; // SWD mode size = send_recv(slu, 1, cmd, slu->cmd_len, data, 52); + if (size == -1) { printf("[!] send_recv STLINK_APIV3_GET_COM_FREQ\n"); - return (int) size; + return((int)size); } int speeds_size = data[8]; - if (speeds_size > STLINK_V3_MAX_FREQ_NB) speeds_size = STLINK_V3_MAX_FREQ_NB; + if (speeds_size > STLINK_V3_MAX_FREQ_NB) { + speeds_size = STLINK_V3_MAX_FREQ_NB; + } for (i = 0; i < speeds_size; i++) map[i] = le_to_h_u32(&data[12 + 4 * i]); @@ -618,14 +670,16 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) { cmd[i++] = (uint8_t)((map[speed_index] >> 24) & 0xFF); size = send_recv(slu, 1, cmd, slu->cmd_len, data, 8); + if (size == -1) { printf("[!] send_recv STLINK_APIV3_SET_COM_FREQ\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } - return -1; + + return(-1); } int _stlink_usb_exit_debug_mode(stlink_t *sl) { @@ -638,12 +692,13 @@ int _stlink_usb_exit_debug_mode(stlink_t *sl) { cmd[i++] = STLINK_DEBUG_EXIT; size = send_only(slu, 1, cmd, slu->cmd_len); + if (size == -1) { printf("[!] send_only STLINK_DEBUG_EXIT\n"); - return (int) size; + return((int)size); } - return 0; + return(0); } int _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { @@ -661,13 +716,13 @@ int _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { if (size == -1) { printf("[!] send_recv STLINK_DEBUG_READMEM_32BIT\n"); - return (int) size; + return((int)size); } - sl->q_len = (int) size; + sl->q_len = (int)size; stlink_print_data(sl); - return 0; + return(0); } int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { @@ -690,23 +745,24 @@ int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { if (size == -1) { printf("[!] send_recv STLINK_DEBUG_READALLREGS\n"); - return (int) size; + return((int)size); } /* V1: regs data from offset 0 */ /* V2: status at offset 0, regs data from offset 4 */ int reg_offset = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 4; - sl->q_len = (int) size; + sl->q_len = (int)size; stlink_print_data(sl); - for(i=reg_offset; i<16; i++) regp->r[i]= read_uint32(sl->q_buf, i*4); + for (i = reg_offset; i < 16; i++) regp->r[i] = read_uint32(sl->q_buf, i * 4); + regp->xpsr = read_uint32(sl->q_buf, reg_offset + 64); regp->main_sp = read_uint32(sl->q_buf, reg_offset + 68); regp->process_sp = read_uint32(sl->q_buf, reg_offset + 72); regp->rw = read_uint32(sl->q_buf, reg_offset + 76); regp->rw2 = read_uint32(sl->q_buf, reg_offset + 80); - if (sl->verbose < 2) return 0; + if (sl->verbose < 2) { return(0); } DLOG("xpsr = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 64)); DLOG("main_sp = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 68)); @@ -714,7 +770,7 @@ int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { DLOG("rw = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 76)); DLOG("rw2 = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 80)); - return 0; + return(0); } int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { @@ -735,15 +791,15 @@ int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { cmd[i++] = STLINK_DEBUG_APIV2_READREG; } - cmd[i++] = (uint8_t) r_idx; + cmd[i++] = (uint8_t)r_idx; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { printf("[!] send_recv STLINK_DEBUG_READREG\n"); - return (int) size; + return((int)size); } - sl->q_len = (int) size; + sl->q_len = (int)size; stlink_print_data(sl); r = read_uint32(sl->q_buf, reg_offset); DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r); @@ -768,7 +824,7 @@ int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { regp->r[r_idx] = r; } - return 0; + return(0); } /* See section C1.6 of the ARMv7-M Architecture Reference Manual */ @@ -776,89 +832,96 @@ int _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, struct stlink_reg uint32_t r; int ret; - sl->q_buf[0] = (unsigned char) r_idx; + sl->q_buf[0] = (unsigned char)r_idx; + for (int i = 1; i < 4; i++) sl->q_buf[i] = 0; ret = _stlink_usb_write_mem32(sl, STLINK_REG_DCRSR, 4); - if (ret == -1) return ret; + + if (ret == -1) { return(ret); } ret = _stlink_usb_read_mem32(sl, STLINK_REG_DCRDR, 4); - if (ret == -1) return ret; + + if (ret == -1) { return(ret); } r = read_uint32(sl->q_buf, 0); DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r); switch (r_idx) { - case 0x14: - regp->primask = (uint8_t) (r & 0xFF); - regp->basepri = (uint8_t) ((r>>8) & 0xFF); - regp->faultmask = (uint8_t) ((r>>16) & 0xFF); - regp->control = (uint8_t) ((r>>24) & 0xFF); - break; - case 0x21: - regp->fpscr = r; - break; - default: - regp->s[r_idx - 0x40] = r; - break; + case 0x14: + regp->primask = (uint8_t)(r & 0xFF); + regp->basepri = (uint8_t)((r >> 8) & 0xFF); + regp->faultmask = (uint8_t)((r >> 16) & 0xFF); + regp->control = (uint8_t)((r >> 24) & 0xFF); + break; + case 0x21: + regp->fpscr = r; + break; + default: + regp->s[r_idx - 0x40] = r; + break; } - return 0; + return(0); } int _stlink_usb_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp) { int ret; ret = _stlink_usb_read_unsupported_reg(sl, 0x14, regp); - if (ret == -1) return ret; + + if (ret == -1) { return(ret); } ret = _stlink_usb_read_unsupported_reg(sl, 0x21, regp); - if (ret == -1) return ret; + + if (ret == -1) { return(ret); } for (int i = 0; i < 32; i++) { - ret = _stlink_usb_read_unsupported_reg(sl, 0x40+i, regp); - if (ret == -1) return ret; + ret = _stlink_usb_read_unsupported_reg(sl, 0x40 + i, regp); + + if (ret == -1) { return(ret); } } - return 0; + return(0); } /* See section C1.6 of the ARMv7-M Architecture Reference Manual */ int _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, struct stlink_reg *regp) { int ret; - if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */ + if (r_idx >= 0x1C && r_idx <= 0x1F) { // primask, basepri, faultmask, or control /* These are held in the same register */ ret = _stlink_usb_read_unsupported_reg(sl, 0x14, regp); - if (ret == -1) return ret; - val = (uint8_t) (val>>24); + if (ret == -1) { return(ret); } + + val = (uint8_t)(val >> 24); switch (r_idx) { - case 0x1C: /* control */ - val = (((uint32_t) val) << 24) | - (((uint32_t) regp->faultmask) << 16) | - (((uint32_t) regp->basepri) << 8) | - ((uint32_t) regp->primask); - break; - case 0x1D: /* faultmask */ - val = (((uint32_t) regp->control) << 24) | - (((uint32_t) val) << 16) | - (((uint32_t) regp->basepri) << 8) | - ((uint32_t) regp->primask); - break; - case 0x1E: /* basepri */ - val = (((uint32_t) regp->control) << 24) | - (((uint32_t) regp->faultmask) << 16) | - (((uint32_t) val) << 8) | - ((uint32_t) regp->primask); - break; - case 0x1F: /* primask */ - val = (((uint32_t) regp->control) << 24) | - (((uint32_t) regp->faultmask) << 16) | - (((uint32_t) regp->basepri) << 8) | - ((uint32_t) val); - break; + case 0x1C: /* control */ + val = (((uint32_t)val) << 24) | + (((uint32_t)regp->faultmask) << 16) | + (((uint32_t)regp->basepri) << 8) | + ((uint32_t)regp->primask); + break; + case 0x1D: /* faultmask */ + val = (((uint32_t)regp->control) << 24) | + (((uint32_t)val) << 16) | + (((uint32_t)regp->basepri) << 8) | + ((uint32_t)regp->primask); + break; + case 0x1E: /* basepri */ + val = (((uint32_t)regp->control) << 24) | + (((uint32_t)regp->faultmask) << 16) | + (((uint32_t)val) << 8) | + ((uint32_t)regp->primask); + break; + case 0x1F: /* primask */ + val = (((uint32_t)regp->control) << 24) | + (((uint32_t)regp->faultmask) << 16) | + (((uint32_t)regp->basepri) << 8) | + ((uint32_t)val); + break; } r_idx = 0x14; @@ -867,14 +930,15 @@ int _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, str write_uint32(sl->q_buf, val); ret = _stlink_usb_write_mem32(sl, STLINK_REG_DCRDR, 4); - if (ret == -1) return ret; - sl->q_buf[0] = (unsigned char) r_idx; + if (ret == -1) { return(ret); } + + sl->q_buf[0] = (unsigned char)r_idx; sl->q_buf[1] = 0; sl->q_buf[2] = 0x01; sl->q_buf[3] = 0; - return _stlink_usb_write_mem32(sl, STLINK_REG_DCRSR, 4); + return(_stlink_usb_write_mem32(sl, STLINK_REG_DCRSR, 4)); } int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) { @@ -899,19 +963,20 @@ int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) { if (size == -1) { printf("[!] send_recv STLINK_DEBUG_WRITEREG\n"); - return (int) size; + return((int)size); } - sl->q_len = (int) size; + + sl->q_len = (int)size; stlink_print_data(sl); - return 0; + return(0); } static stlink_backend_t _stlink_usb_backend = { _stlink_usb_close, _stlink_usb_exit_debug_mode, _stlink_usb_enter_swd_mode, - NULL, // no enter_jtag_mode here... + NULL, // don't enter_jtag_mode here... _stlink_usb_exit_dfu_mode, _stlink_usb_core_id, _stlink_usb_reset, @@ -943,17 +1008,19 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL int ret = -1; int config; - sl = calloc(1, sizeof (stlink_t)); - slu = calloc(1, sizeof (struct stlink_libusb)); + sl = calloc(1, sizeof(stlink_t)); + slu = calloc(1, sizeof(struct stlink_libusb)); + + if (sl == NULL) { goto on_malloc_error; } - if (sl == NULL) goto on_malloc_error; - if (slu == NULL) goto on_malloc_error; + if (slu == NULL) { goto on_malloc_error; } ugly_init(verbose); sl->backend = &_stlink_usb_backend; sl->backend_data = slu; sl->core_stat = TARGET_UNKNOWN; + if (libusb_init(&(slu->libusb_ctx))) { WLOG("failed to init libusb context, wrong version of libraries?\n"); goto on_error; @@ -966,53 +1033,58 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL #endif libusb_device **list; - /* @TODO: We should use ssize_t and use it as a counter if > 0. - * As per libusb API: ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device ***list) - */ - int cnt = (int) libusb_get_device_list(slu->libusb_ctx, &list); + // TODO: We should use ssize_t and use it as a counter if > 0. + // As per libusb API: ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device ***list) + int cnt = (int)libusb_get_device_list(slu->libusb_ctx, &list); struct libusb_device_descriptor desc; int devBus = 0; int devAddr = 0; - /* @TODO: Reading a environment variable in a usb open function is not very nice, this should be refactored - * and moved into the CLI tools, and instead of giving USB_BUS:USB_ADDR a real stlink serial string should - * be passed to this function. Probably people are using this but this is very odd because as programmer - * can change to multiple busses and it is better to detect them based on serial. - */ + // TODO: Reading a environment variable in a usb open function is not very nice, this should + // be refactored and moved into the CLI tools, and instead of giving USB_BUS:USB_ADDR a real + // stlink serial string should be passed to this function. Probably people are using this + // but this is very odd because as programmer can change to multiple busses and it is better + // to detect them based on serial. char *device = getenv("STLINK_DEVICE"); + if (device) { - char *c = strchr(device,':'); + char *c = strchr(device, ':'); + if (c == NULL) { WLOG("STLINK_DEVICE must be : format\n"); goto on_error; } + devBus = atoi(device); *c++ = 0; devAddr = atoi(c); - ILOG("bus %03d dev %03d\n",devBus, devAddr); + ILOG("bus %03d dev %03d\n", devBus, devAddr); } while (cnt--) { struct libusb_device_handle *handle; libusb_get_device_descriptor(list[cnt], &desc); - if (desc.idVendor != STLINK_USB_VID_ST) continue; + + if (desc.idVendor != STLINK_USB_VID_ST) { continue; } if (devBus && devAddr) { - if ((libusb_get_bus_number(list[cnt]) != devBus) || (libusb_get_device_address(list[cnt]) != devAddr)) { + if ((libusb_get_bus_number(list[cnt]) != devBus) || + (libusb_get_device_address(list[cnt]) != devAddr)) { continue; } } ret = libusb_open(list[cnt], &handle); - if (ret) continue; // could not open device + + if (ret) { continue; } // could not open device sl->serial_size = libusb_get_string_descriptor_ascii( - handle, desc.iSerialNumber, (unsigned char *)sl->serial, sizeof(sl->serial)); + handle, desc.iSerialNumber, (unsigned char *)sl->serial, sizeof(sl->serial)); libusb_close(handle); - if (sl->serial_size < 0) continue; // could not read serial + if (sl->serial_size < 0) { continue; } // could not read serial // if no serial provided, or if serial match device, fixup version and protocol if (((serial == NULL) || (*serial == 0)) || (memcmp(serial, &sl->serial, sl->serial_size) == 0)) { @@ -1024,18 +1096,23 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL } else if (STLINK_V3_USB_PID(desc.idProduct)) { sl->version.stlink_v = 3; } + break; } } if (cnt < 0) { - WLOG ("Couldn't find %s ST-Link devices\n", (devBus && devAddr) ? "matched":"any"); + WLOG ("Couldn't find %s ST-Link devices\n", (devBus && devAddr) ? "matched" : "any"); goto on_error; } else { ret = libusb_open(list[cnt], &slu->usb_handle); + if (ret != 0) { - WLOG("Error %d (%s) opening ST-Link v%d device %03d:%03d\n", ret, strerror (errno), - sl->version.stlink_v, libusb_get_bus_number(list[cnt]), libusb_get_device_address(list[cnt])); + WLOG("Error %d (%s) opening ST-Link v%d device %03d:%03d\n", ret, + strerror(errno), + sl->version.stlink_v, + libusb_get_bus_number(list[cnt]), + libusb_get_device_address(list[cnt])); libusb_free_device_list(list, 1); goto on_error; } @@ -1045,6 +1122,7 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL if (libusb_kernel_driver_active(slu->usb_handle, 0) == 1) { ret = libusb_detach_kernel_driver(slu->usb_handle, 0); + if (ret < 0) { WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-ret)); goto on_libusb_error; @@ -1052,15 +1130,16 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL } if (libusb_get_configuration(slu->usb_handle, &config)) { - /* this may fail for a previous configured device */ + // this may fail for a previous configured device WLOG("libusb_get_configuration()\n"); goto on_libusb_error; } if (config != 1) { printf("setting new configuration (%d -> 1)\n", config); + if (libusb_set_configuration(slu->usb_handle, 1)) { - /* this may fail for a previous configured device */ + // this may fail for a previous configured device WLOG("libusb_set_configuration() failed\n"); goto on_libusb_error; } @@ -1071,8 +1150,9 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL goto on_libusb_error; } - // TODO - could use the scanning techniq from stm8 code here... + // TODO: Could use the scanning technique from STM8 code here... slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN; + if (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO || desc.idProduct == STLINK_USB_PID_STLINK_32L_AUDIO || desc.idProduct == STLINK_USB_PID_STLINK_V2_1 || @@ -1086,17 +1166,14 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL } slu->sg_transfer_idx = 0; - slu->cmd_len = (slu->protocoll == 1) ? STLINK_SG_SIZE: STLINK_CMD_SIZE; - - // Initialize stlink version (sl->version) - stlink_version(sl); + slu->cmd_len = (slu->protocoll == 1) ? STLINK_SG_SIZE : STLINK_CMD_SIZE; - // Initialize stlink version (sl->version) + // initialize stlink version (sl->version) stlink_version(sl); if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { - // This seems to work, and is unnecessary information for the user. - // Demoted to debug -- REW + // this seems to work, and is unnecessary information for the user. + // demoted to debug -- REW DLOG("-- exit_dfu_mode\n"); stlink_exit_dfu_mode(sl); } @@ -1104,78 +1181,86 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL sl->freq = freq; // set the speed before entering the mode as the chip discovery phase // should be done at this speed too - // Set the stlink clock speed (default is 1800kHz) + // set the stlink clock speed (default is 1800kHz) DLOG("JTAG/SWD freq set to %d\n", freq); + switch (freq) { - case 5: - stlink_set_swdclk(sl, STLINK_SWDCLK_5KHZ_DIVISOR); - break; - case 15: - stlink_set_swdclk(sl, STLINK_SWDCLK_15KHZ_DIVISOR); - break; - case 25: - stlink_set_swdclk(sl, STLINK_SWDCLK_25KHZ_DIVISOR); - break; - case 50: - stlink_set_swdclk(sl, STLINK_SWDCLK_50KHZ_DIVISOR); - break; - case 100: - stlink_set_swdclk(sl, STLINK_SWDCLK_100KHZ_DIVISOR); - break; - case 125: - stlink_set_swdclk(sl, STLINK_SWDCLK_125KHZ_DIVISOR); - break; - case 240: - stlink_set_swdclk(sl, STLINK_SWDCLK_240KHZ_DIVISOR); - break; - case 480: - stlink_set_swdclk(sl, STLINK_SWDCLK_480KHZ_DIVISOR); - break; - case 950: - stlink_set_swdclk(sl, STLINK_SWDCLK_950KHZ_DIVISOR); - break; - case 1200: - stlink_set_swdclk(sl, STLINK_SWDCLK_1P2MHZ_DIVISOR); - break; - case 0: case 1800: - stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR); - break; - case 4000: - stlink_set_swdclk(sl, STLINK_SWDCLK_4MHZ_DIVISOR); - break; + case 5: + stlink_set_swdclk(sl, STLINK_SWDCLK_5KHZ_DIVISOR); + break; + case 15: + stlink_set_swdclk(sl, STLINK_SWDCLK_15KHZ_DIVISOR); + break; + case 25: + stlink_set_swdclk(sl, STLINK_SWDCLK_25KHZ_DIVISOR); + break; + case 50: + stlink_set_swdclk(sl, STLINK_SWDCLK_50KHZ_DIVISOR); + break; + case 100: + stlink_set_swdclk(sl, STLINK_SWDCLK_100KHZ_DIVISOR); + break; + case 125: + stlink_set_swdclk(sl, STLINK_SWDCLK_125KHZ_DIVISOR); + break; + case 240: + stlink_set_swdclk(sl, STLINK_SWDCLK_240KHZ_DIVISOR); + break; + case 480: + stlink_set_swdclk(sl, STLINK_SWDCLK_480KHZ_DIVISOR); + break; + case 950: + stlink_set_swdclk(sl, STLINK_SWDCLK_950KHZ_DIVISOR); + break; + case 1200: + stlink_set_swdclk(sl, STLINK_SWDCLK_1P2MHZ_DIVISOR); + break; + case 0: case 1800: + stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR); + break; + case 4000: + stlink_set_swdclk(sl, STLINK_SWDCLK_4MHZ_DIVISOR); + break; } if (reset == 2) { - stlink_jtag_reset(sl,0); - if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); - stlink_force_debug(sl); - stlink_jtag_reset(sl,1); - usleep(10000); + stlink_jtag_reset(sl, 0); + + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } + + stlink_force_debug(sl); + stlink_jtag_reset(sl, 1); + usleep(10000); } - if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } if (reset == 1) { - if ( sl->version.stlink_v > 1) stlink_jtag_reset(sl, 2); + if ( sl->version.stlink_v > 1) { stlink_jtag_reset(sl, 2); } + stlink_reset(sl); usleep(10000); } stlink_load_device_params(sl); - return sl; + return(sl); + +on_libusb_error: + stlink_close(sl); + return(NULL); - on_libusb_error: - stlink_close(sl); - return NULL; +on_error: - on_error: - if (slu->libusb_ctx) libusb_exit(slu->libusb_ctx); + if (slu->libusb_ctx) { libusb_exit(slu->libusb_ctx); } - on_malloc_error: - if (sl != NULL) free(sl); - if (slu != NULL) free(slu); - return NULL; +on_malloc_error: + + if (sl != NULL) { free(sl); } + + if (slu != NULL) { free(slu); } + + return(NULL); } static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { @@ -1185,7 +1270,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { size_t slcnt = 0; size_t slcur = 0; - /* Count stlink */ + /* Count STLINKs */ while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; int ret = libusb_get_device_descriptor(dev, &desc); @@ -1195,7 +1280,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { break; } - if (desc.idVendor != STLINK_USB_VID_ST) continue; + if (desc.idVendor != STLINK_USB_VID_ST) { continue; } if (!STLINK_SUPPORTED_USB_PID(desc.idProduct)) { WLOG("skipping ST device : %#04x:%#04x)\n", desc.idVendor, desc.idProduct); @@ -1205,15 +1290,16 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { slcnt++; } - /* Allocate list of pointers */ - _sldevs = calloc(slcnt, sizeof(stlink_t *)); + _sldevs = calloc(slcnt, sizeof(stlink_t *)); // allocate list of pointers + if (!_sldevs) { *sldevs = NULL; - return 0; + return(0); } - /* Open stlinks and attach to list */ + /* Open STLINKS and attach them to list */ i = 0; + while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; int ret = libusb_get_device_descriptor(dev, &desc); @@ -1223,10 +1309,10 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { break; } - if (!STLINK_SUPPORTED_USB_PID(desc.idProduct)) continue; + if (!STLINK_SUPPORTED_USB_PID(desc.idProduct)) { continue; } struct libusb_device_handle* handle; - char serial[STLINK_SERIAL_MAX_SIZE] = {0,}; + char serial[STLINK_SERIAL_MAX_SIZE] = {0, }; ret = libusb_open(dev, &handle); @@ -1236,15 +1322,18 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { } else { ELOG("Failed to open USB device %#06x:%#06x, libusb error: %d)\n", desc.idVendor, desc.idProduct, ret); } + break; } + ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)&serial, sizeof(serial)); libusb_close(handle); - if (ret < 0) continue; + if (ret < 0) { continue; } stlink_t *sl = stlink_open_usb(0, 1, serial, 0); + if (!sl) { ELOG("Failed to open USB device %#06x:%#06x\n", desc.idVendor, desc.idProduct); continue; @@ -1255,7 +1344,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { *sldevs = _sldevs; - return slcur; + return(slcur); } size_t stlink_probe_usb(stlink_t **stdevs[]) { @@ -1267,10 +1356,12 @@ size_t stlink_probe_usb(stlink_t **stdevs[]) { ssize_t cnt; r = libusb_init(NULL); - if (r < 0) return 0; + + if (r < 0) { return(0); } cnt = libusb_get_device_list(NULL, &devs); - if (cnt < 0) return 0; + + if (cnt < 0) { return(0); } slcnt = stlink_probe_usb_devs(devs, &sldevs); libusb_free_device_list(devs, 1); @@ -1279,12 +1370,14 @@ size_t stlink_probe_usb(stlink_t **stdevs[]) { *stdevs = sldevs; - return slcnt; + return(slcnt); } void stlink_probe_usb_free(stlink_t ***stdevs, size_t size) { - if (stdevs == NULL || *stdevs == NULL || size == 0) return; - for (size_t n = 0; n < size; n++) stlink_close((*stdevs)[n]); + if (stdevs == NULL || *stdevs == NULL || size == 0) { return; } + + for (size_t n = 0; n < size; n++) { stlink_close((*stdevs)[n]); } + free(*stdevs); *stdevs = NULL; } diff --git a/src/stlink-lib/usb.h b/src/stlink-lib/usb.h new file mode 100644 index 000000000..d11f17381 --- /dev/null +++ b/src/stlink-lib/usb.h @@ -0,0 +1,77 @@ +/* + * File: usb.h + * Author: karl + */ + +#ifndef STLINK_USB_H +#define STLINK_USB_H + +#include + +#include +#include +#include "logging.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define STLINK_USB_VID_ST 0x0483 +#define STLINK_USB_PID_STLINK 0x3744 +#define STLINK_USB_PID_STLINK_32L 0x3748 +#define STLINK_USB_PID_STLINK_32L_AUDIO 0x374a +#define STLINK_USB_PID_STLINK_NUCLEO 0x374b +#define STLINK_USB_PID_STLINK_V2_1 0x3752 +#define STLINK_USB_PID_STLINK_V3_USBLOADER 0x374d +#define STLINK_USB_PID_STLINK_V3E_PID 0x374e +#define STLINK_USB_PID_STLINK_V3S_PID 0x374f +#define STLINK_USB_PID_STLINK_V3_2VCP_PID 0x3753 + +#define STLINK_V1_USB_PID(pid) ((pid) == STLINK_USB_PID_STLINK) + +#define STLINK_V2_USB_PID(pid) ((pid) == STLINK_USB_PID_STLINK_32L || \ + (pid) == STLINK_USB_PID_STLINK_32L_AUDIO || \ + (pid) == STLINK_USB_PID_STLINK_NUCLEO) + +#define STLINK_V2_1_USB_PID(pid) ((pid) == STLINK_USB_PID_STLINK_V2_1) + +#define STLINK_V3_USB_PID(pid) ((pid) == STLINK_USB_PID_STLINK_V3_USBLOADER || \ + (pid) == STLINK_USB_PID_STLINK_V3E_PID || \ + (pid) == STLINK_USB_PID_STLINK_V3S_PID || \ + (pid) == STLINK_USB_PID_STLINK_V3_2VCP_PID) + +#define STLINK_SUPPORTED_USB_PID(pid) (STLINK_V1_USB_PID(pid) || \ + STLINK_V2_USB_PID(pid) || \ + STLINK_V2_1_USB_PID(pid) || \ + STLINK_V3_USB_PID(pid)) + +#define STLINK_SG_SIZE 31 +#define STLINK_CMD_SIZE 16 + +struct stlink_libusb { + libusb_context* libusb_ctx; + libusb_device_handle* usb_handle; + unsigned int ep_req; + unsigned int ep_rep; + int protocoll; + unsigned int sg_transfer_idx; + unsigned int cmd_len; +}; + +/** + * Open a stlink + * @param verbose Verbosity loglevel + * @param reset Reset stlink programmer + * @param serial Serial number to search for, when NULL the first stlink found is opened (binary format) + * @retval NULL Error while opening the stlink + * @retval !NULL Stlink found and ready to use + */ +stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq); +size_t stlink_probe_usb(stlink_t **stdevs[]); +void stlink_probe_usb_free(stlink_t **stdevs[], size_t size); + +#ifdef __cplusplus +} +#endif + +#endif // STLINK_USB_H diff --git a/src/tools/flash_opts.c b/src/tools/flash_opts.c deleted file mode 100644 index c8d7841de..000000000 --- a/src/tools/flash_opts.c +++ /dev/null @@ -1,321 +0,0 @@ -#include -#include -#include - -#include - -static bool starts_with(const char * str, const char * prefix) { - size_t n = strlen(prefix); - if (strlen(str) < n) return false; - - return (0 == strncmp(str, prefix, n)); -} - -// support positive integer from 0 to UINT64_MAX -// support decimal, hexadecimal, octal, binary format like 0xff 12 1k 1M, 0b1001 -// negative numbers are not supported -// return 0 if success else return -1 -static int get_long_integer_from_char_array (const char *const str, uint64_t *read_value) { - uint64_t value; - char *tail; - - // hexadecimal - if (starts_with (str, "0x") || starts_with (str, "0X")) { - value = strtoul (str + 2, &tail, 16); - } - // binary - else if (starts_with (str, "0b") || starts_with (str, "0B")) { - value = strtoul (str + 2, &tail, 2); - } - // octal - else if (starts_with (str, "0")) { - value = strtoul (str + 1, &tail, 8); - } - // decimal - else { - value = strtoul (str, &tail, 10); - } - - if (((tail[0] == 'k') || (tail[0] == 'K')) && (tail[1] == '\0')) { - value = value * 1024; - } - else if (((tail[0] == 'm') || (tail[0] == 'M')) && (tail[1] == '\0')) { - value = value * 1024 * 1024; - } - else if (tail[0] == '\0') { - // value not change - } - else { - return -1; - } - *read_value = value; - return 0; -} - -// support positive integer from 0 to UINT32_MAX -// support decimal, hexadecimal, octal, binary format like 0xff 12 1k 1M, 0b1001 -// negative numbers are not supported -// return 0 if success else return -1 -static int get_integer_from_char_array (const char *const str, uint32_t *read_value) { - uint64_t value; - int result = get_long_integer_from_char_array (str, &value); - if (result != 0) { - return result; - } - else if (value > UINT32_MAX) { - fprintf (stderr, "*** Error: Integer greater than UINT32_MAX, \ -cannot convert to int32_t\n"); - return -1; - } - else { - *read_value = (uint32_t)value; - return 0; - } -} - -static int invalid_args(const char *expected) { - fprintf(stderr, "*** Error: Expected args for this command: %s\n", expected); - return -1; -} - -static int bad_arg(const char *arg) { - fprintf(stderr, "*** Error: Invalid value for %s\n", arg); - return -1; -} - -int flash_get_opts(struct flash_opts* o, int ac, char** av) { - - // defaults - memset(o, 0, sizeof(*o)); - o->log_level = STND_LOG_LEVEL; - - // options - int result; - while (ac >= 1) { - if (strcmp(av[0], "--version") == 0) { - printf("v%s\n", STLINK_VERSION); - exit(EXIT_SUCCESS); - } - else if (strcmp(av[0], "--debug") == 0) { - o->log_level = DEBUG_LOG_LEVEL; - } - else if (strcmp(av[0], "--opt") == 0) { - o->opt = ENABLE_OPT; - } - else if (strcmp(av[0], "--reset") == 0) { - o->reset = 1; - } - else if (strcmp(av[0], "--serial") == 0 || starts_with(av[0], "--serial=")) { - const char * serial; - if (strcmp(av[0], "--serial") == 0) { - ac--; - av++; - if (ac < 1) return -1; - serial = av[0]; - } - else { - serial = av[0] + strlen("--serial="); - } - /** @todo This is not really portable, as strlen really returns size_t we need to obey and not cast it to a signed type. */ - int j = (int)strlen(serial); - int length = j / 2; // the length of the destination-array - if (j % 2 != 0) return -1; - for (size_t k = 0; j >= 0 && k < sizeof(o->serial); ++k, j -= 2) { - char buffer[3] = {0}; - memcpy(buffer, serial + j, 2); - o->serial[length - k] = (uint8_t)strtol(buffer, NULL, 16); - } - } - else if (strcmp(av[0], "--area") == 0 || starts_with(av[0], "--area=")) { - const char * area; - if (strcmp(av[0], "--area") == 0) { - ac--; - av++; - if (ac < 1) return -1; - area = av[0]; - } - else { - area = av[0] + strlen("--area="); - } - if (strcmp(area, "main") == 0) - o->area = FLASH_MAIN_MEMORY; - else if (strcmp(area, "system") == 0) - o->area = FLASH_SYSTEM_MEMORY; - else if (strcmp(area, "otp") == 0) - o->area = FLASH_OTP; - else if (strcmp(area, "option") == 0) - o->area = FLASH_OPTION_BYTES; - else - return -1; - - } - else if (strcmp(av[0], "--freq") == 0 || starts_with(av[0], "--freq=")) { - const char* freq; - if (strcmp(av[0], "--freq") == 0) { - ac--; - av++; - if (ac < 1) return -1; - freq = av[0]; - } - else { - freq = av[0] + strlen("--freq="); - } - if (strcmp(freq, "5K") == 0 || strcmp(freq, "5k") == 0) { - o->freq = 5; - } - else if (strcmp(freq, "15K") == 0 || strcmp(freq, "15k") == 0) { - o->freq = 15; - } - else if (strcmp(freq, "25K") == 0 || strcmp(freq, "25k") == 0) { - o->freq = 25; - } - else if (strcmp(freq, "50K") == 0 || strcmp(freq, "50k") == 0) { - o->freq = 50; - } - else if (strcmp(freq, "100K") == 0 || strcmp(freq, "100k") == 0) { - o->freq = 100; - } - else if (strcmp(freq, "125K") == 0 || strcmp(freq, "125k") == 0) { - o->freq = 125; - } - else if (strcmp(freq, "240K") == 0 || strcmp(freq, "240k") == 0) { - o->freq = 240; - } - else if (strcmp(freq, "480K") == 0 || strcmp(freq, "480k") == 0) { - o->freq = 480; - } - else if (strcmp(freq, "950K") == 0 || strcmp(freq, "950k") == 0) { - o->freq = 950; - } - else if (strcmp(freq, "1200K") == 0 || strcmp(freq, "1200k") == 0 || strcmp(freq, "1.2M") == 0 || strcmp(freq, "1.2m") == 0) { - o->freq = 1200; - } - else if (strcmp(freq, "1800K") == 0 || strcmp(freq, "1800k") == 0 || strcmp(freq, "1.8M") == 0 || strcmp(freq, "1.8m") == 0) { - o->freq = 1800; - } - else if (strcmp(freq, "4000K") == 0 || strcmp(freq, "4000k") == 0 || strcmp(freq, "4M") == 0 || strcmp(freq, "4m") == 0) { - o->freq = 4000; - } - else - return -1; - } - else if (strcmp(av[0], "--format") == 0 || starts_with(av[0], "--format=")) { - const char * format; - if (strcmp(av[0], "--format") == 0) { - ac--; - av++; - if (ac < 1) return -1; - format = av[0]; - } - else { - format = av[0] + strlen("--format="); - } - if (strcmp(format, "binary") == 0) - o->format = FLASH_FORMAT_BINARY; - else if (strcmp(format, "ihex") == 0) - o->format = FLASH_FORMAT_IHEX; - else - return bad_arg("format"); - } - else if ( starts_with(av[0], "--flash=") ) { - const char *arg = av[0] + strlen("--flash="); - - uint32_t flash_size; - result = get_integer_from_char_array(arg, &flash_size); - if (result != 0) return bad_arg ("--flash"); - else o->flash_size = (size_t) flash_size; - } - else if (strcmp(av[0],"--connect-under-reset")== 0){ - o->connect_under_reset = true; - } - else { - break; // non-option found - } - - ac--; - av++; - } - - // command and (optional) device name - while (ac >= 1) { - if (strcmp(av[0], "erase") == 0) { - if (o->cmd != FLASH_CMD_NONE) return -1; - o->cmd = FLASH_CMD_ERASE; - } - else if (strcmp(av[0], "read") == 0) { - if (o->cmd != FLASH_CMD_NONE) return -1; - o->cmd = FLASH_CMD_READ; - } - else if (strcmp(av[0], "write") == 0) { - if (o->cmd != FLASH_CMD_NONE) return -1; - o->cmd = FLASH_CMD_WRITE; - } - else if (strcmp(av[0], "reset") == 0) { - if (o->cmd != FLASH_CMD_NONE) return -1; - o->cmd = CMD_RESET; - } - else { - break; - } - - ac--; - av++; - } - - switch(o->cmd) { - case FLASH_CMD_NONE: // no command found - return -1; - - case FLASH_CMD_ERASE: // no more arguments expected - if (ac != 0) return -1; - break; - - case FLASH_CMD_READ: // expect filename, addr and size - if ((o->area == FLASH_OPTION_BYTES) &&(ac == 0)) break; - if (ac != 3) return invalid_args("read "); - if (ac != 3) return -1; - o->filename = av[0]; - uint32_t address; - result = get_integer_from_char_array(av[1], &address); - if (result != 0) return bad_arg ("addr"); - else o->addr = (stm32_addr_t) address; - - uint32_t size; - result = get_integer_from_char_array(av[2], &size); - if (result != 0) return bad_arg ("size"); - else o->size = (size_t) size; - - break; - - case FLASH_CMD_WRITE: - if (o->area == FLASH_OPTION_BYTES){ - if (ac != 1) return -1; - - uint32_t val; - result = get_integer_from_char_array(av[0], &val); - if (result != 0) return bad_arg ("val"); - else o->val = (uint32_t) val; - - } - else if (o->format == FLASH_FORMAT_BINARY) { // expect filename and addr - if (ac != 2) return invalid_args("write "); - o->filename = av[0]; - uint32_t addr; - result = get_integer_from_char_array(av[1], &addr); - if (result != 0) return bad_arg ("addr"); - else o->addr = (stm32_addr_t) addr; - } - else if (o->format == FLASH_FORMAT_IHEX) { // expect filename - if (ac != 1) return invalid_args("write "); - o->filename = av[0]; - } - else { - return -1; // should have been caught during format parsing - } - break; - - default: break ; - } - - return 0; -} diff --git a/src/usb.h b/src/usb.h deleted file mode 100644 index 5c1f5b7ca..000000000 --- a/src/usb.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * File: usb.h - * Author: karl - * - * Created on October 1, 2011, 11:29 PM - */ - -#ifndef STLINK_USB_H -#define STLINK_USB_H - -#include - -#include -#include "libusb_settings.h" -#include "logging.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define STLINK_USB_VID_ST 0x0483 -#define STLINK_USB_PID_STLINK 0x3744 -#define STLINK_USB_PID_STLINK_32L 0x3748 -#define STLINK_USB_PID_STLINK_32L_AUDIO 0x374a -#define STLINK_USB_PID_STLINK_NUCLEO 0x374b -#define STLINK_USB_PID_STLINK_V2_1 0x3752 -#define STLINK_USB_PID_STLINK_V3_USBLOADER 0x374d -#define STLINK_USB_PID_STLINK_V3E_PID 0x374e -#define STLINK_USB_PID_STLINK_V3S_PID 0x374f -#define STLINK_USB_PID_STLINK_V3_2VCP_PID 0x3753 - -#define STLINK_V1_USB_PID(pid) ((pid) == STLINK_USB_PID_STLINK ) - -#define STLINK_V2_USB_PID(pid) ((pid) == STLINK_USB_PID_STLINK_32L || \ - (pid) == STLINK_USB_PID_STLINK_32L_AUDIO || \ - (pid) == STLINK_USB_PID_STLINK_NUCLEO) - -#define STLINK_V2_1_USB_PID(pid) ( (pid) == STLINK_USB_PID_STLINK_V2_1 ) - -#define STLINK_V3_USB_PID(pid) ((pid) == STLINK_USB_PID_STLINK_V3_USBLOADER || \ - (pid) == STLINK_USB_PID_STLINK_V3E_PID || \ - (pid) == STLINK_USB_PID_STLINK_V3S_PID || \ - (pid) == STLINK_USB_PID_STLINK_V3_2VCP_PID ) - -#define STLINK_SUPPORTED_USB_PID(pid) ( STLINK_V1_USB_PID(pid) || \ - STLINK_V2_USB_PID(pid) || \ - STLINK_V2_1_USB_PID(pid) || \ - STLINK_V3_USB_PID(pid)) - -#define STLINK_SG_SIZE 31 -#define STLINK_CMD_SIZE 16 - - struct stlink_libusb { - libusb_context* libusb_ctx; - libusb_device_handle* usb_handle; - unsigned int ep_req; - unsigned int ep_rep; - int protocoll; - unsigned int sg_transfer_idx; - unsigned int cmd_len; - }; - - /** - * Open a stlink - * @param verbose Verbosity loglevel - * @param reset Reset stlink programmer - * @param serial Serial number to search for, when NULL the first stlink found is opened (binary format) - * @retval NULL Error while opening the stlink - * @retval !NULL Stlink found and ready to use - */ - stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq); - size_t stlink_probe_usb(stlink_t **stdevs[]); - void stlink_probe_usb_free(stlink_t **stdevs[], size_t size); - -#ifdef __cplusplus -} -#endif - -#endif /* STLINK_USB_H */ diff --git a/src/getopt/LICENSE.txt b/src/win32/getopt/LICENSE.txt similarity index 100% rename from src/getopt/LICENSE.txt rename to src/win32/getopt/LICENSE.txt diff --git a/src/getopt/README.md b/src/win32/getopt/README.md similarity index 78% rename from src/getopt/README.md rename to src/win32/getopt/README.md index 9bf81fa73..2ec27c2d5 100644 --- a/src/getopt/README.md +++ b/src/win32/getopt/README.md @@ -1,10 +1,11 @@ getopt_port =========== -[Kim Gräsman](http://grundlig.wordpress.com) +[Kim Gräsman](http://grundlig.wordpress.com) [@kimgr](http://twitter.com/kimgr) -An original implementation of `getopt` and `getopt_long` with limited GNU extensions. Provided under the BSD license, to allow non-GPL projects to use `getopt`-style command-line parsing. +An original implementation of `getopt` and `getopt_long` with limited GNU extensions. +Provided under the BSD license, to allow non-GPL projects to use `getopt`-style command-line parsing. So far only built with Visual C++, but has no inherently non-portable constructs. @@ -18,4 +19,4 @@ See also: * [XGetOpt](http://www.codeproject.com/Articles/1940/XGetopt-A-Unix-compatible-getopt-for-MFC-and-Win32) -- No `getopt_long` support. * [Free Getopt](https://sourceforge.net/projects/freegetopt/) -- No `getopt_long` support. -For license terms, see LICENSE.txt. \ No newline at end of file +For license terms, see LICENSE.txt. diff --git a/src/win32/getopt/getopt.c b/src/win32/getopt/getopt.c new file mode 100644 index 000000000..85e8804d8 --- /dev/null +++ b/src/win32/getopt/getopt.c @@ -0,0 +1,201 @@ +#include +#include + +#include "getopt.h" + +#if !defined(_MSC_VER) +const int no_argument = 0; +const int required_argument = 1; +const int optional_argument = 2; +#endif + +char* optarg; +int optopt; +int optind = 1; // The variable optind [...] shall be initialized to 1 by the system +int opterr; + +static char* optcursor = NULL; + +/* Implemented based on [1] and [2] for optional arguments. + * optopt is handled FreeBSD-style, per [3]. + * Other GNU and FreeBSD extensions are purely accidental. + * + * [1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html + * [2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html + * [3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE + */ +int getopt(int argc, char* const argv[], const char* optstring) { + int optchar = -1; + const char* optdecl = NULL; + + optarg = NULL; + opterr = 0; + optopt = 0; + + /* Unspecified, but we need it to avoid overrunning the argv bounds. */ + if (optind >= argc) { goto no_more_optchars; } + + /* If, when getopt() is called argv[optind] is a null pointer, + * getopt() shall return -1 without changing optind. + */ + if (argv[optind] == NULL) { goto no_more_optchars; } + + /* If, when getopt() is called *argv[optind] is not the character '-', + * getopt() shall return -1 without changing optind. + */ + if (*argv[optind] != '-') { goto no_more_optchars; } + + /* If, when getopt() is called argv[optind] points to the string "-", + * getopt() shall return -1 without changing optind. + */ + if (strcmp(argv[optind], "-") == 0) { goto no_more_optchars; } + + /* If, when getopt() is called argv[optind] points to the string "--", + * getopt() shall return -1 after incrementing optind. + */ + if (strcmp(argv[optind], "--") == 0) { + ++optind; + goto no_more_optchars; + } + + if (optcursor == NULL || *optcursor == '\0') { optcursor = argv[optind] + 1; } + + optchar = *optcursor; + + /* FreeBSD: The variable optopt saves the last known option character returned by getopt(). */ + optopt = optchar; + + /* The getopt() function shall return the next option character (if one is found) + * from argv that matches a character in optstring, if there is one that matches. + */ + optdecl = strchr(optstring, optchar); + + if (optdecl) { + /* [I]f a character is followed by a colon, the option takes an argument. */ + if (optdecl[1] == ':') { + optarg = ++optcursor; + + if (*optarg == '\0') { + /* GNU extension: Two colons mean an option takes an optional arg; + * if there is text in the current argv-element (i.e., in the same word + * as the option name itself, for example, "-oarg"), then it is returned + * in optarg, otherwise optarg is set to zero. + */ + if (optdecl[2] != ':') { + /* If the option was the last character in the string pointed to by + * an element of argv, then optarg shall contain the next element + * of argv, and optind shall be incremented by 2. If the resulting + * value of optind is greater than argc, this indicates a missing + * option-argument, and getopt() shall return an error indication. + * Otherwise, optarg shall point to the string following the + * option character in that element of argv, and optind shall be + * incremented by 1. + */ + if (++optind < argc) { + optarg = argv[optind]; + } else { + /* If it detects a missing option-argument, it shall return the + * colon character ( ':' ) if the first character of optstring + * was a colon, or a question-mark character ( '?' ) otherwise. + */ + optarg = NULL; + optchar = (optstring[0] == ':') ? ':' : '?'; + } + } else { + optarg = NULL; + } + } + + optcursor = NULL; + } + } else { + /* If getopt() encounters an option character that is not contained in + * optstring, it shall return the question-mark ( '?' ) character. + */ + optchar = '?'; + } + + if (optcursor == NULL || *++optcursor == '\0') { ++optind; } + + return(optchar); + +no_more_optchars: + optcursor = NULL; + return(-1); +} + +/* Implementation based on http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html */ +int getopt_long(int argc, + char* const argv[], + const char* optstring, + const struct option* longopts, + int* longindex) { + const struct option* o = longopts; + const struct option* match = NULL; + int num_matches = 0; + size_t argument_name_length = 0; + const char* current_argument = NULL; + int retval = -1; + + optarg = NULL; + optopt = 0; + + if (optind >= argc) { return(-1); } + + if (strlen(argv[optind]) < 3 || strncmp(argv[optind], "--", 2) != 0) { + return(getopt(argc, argv, optstring)); + } + + // it's an option; starts with -- and is longer than two chars + current_argument = argv[optind] + 2; + argument_name_length = strcspn(current_argument, "="); + + for ( ; o->name; ++o) + if (strncmp(o->name, current_argument, argument_name_length) == 0) { + match = o; + ++num_matches; + } + + + if (num_matches == 1) { + /* If longindex is not NULL, it points to a variable which is set to the + * index of the long option relative to longopts. + */ + if (longindex) { *longindex = (match - longopts); } + + /* If flag is NULL, then getopt_long() shall return val. + * Otherwise, getopt_long() returns 0, and flag shall point to a variable + * which shall be set to val if the option is found, but left unchanged if + * the option is not found. + */ + if (match->flag) { *(match->flag) = match->val; } + + retval = match->flag ? 0 : match->val; + + if (match->has_arg != no_argument) { + optarg = strchr(argv[optind], '='); + + if (optarg != NULL) { ++optarg; } + + if (match->has_arg == required_argument) { + /* Only scan the next argv for required arguments. Behavior is not + specified, but has been observed with Ubuntu and macOS. */ + if (optarg == NULL && ++optind < argc) { optarg = argv[optind]; } + + if (optarg == NULL) { retval = ':'; } + } + } else if (strchr(argv[optind], '=')) { + /* An argument was provided to a non-argument option. + * I haven't seen this specified explicitly, but both GNU and BSD-based + * implementations show this behavior. + */ + retval = '?'; + } + } else { + // unknown option or ambiguous match + retval = '?'; + } + + ++optind; + return(retval); +} diff --git a/src/getopt/getopt.h b/src/win32/getopt/getopt.h similarity index 67% rename from src/getopt/getopt.h rename to src/win32/getopt/getopt.h index bc189b9d4..3aaf73bed 100644 --- a/src/getopt/getopt.h +++ b/src/win32/getopt/getopt.h @@ -20,16 +20,19 @@ extern char* optarg; extern int optind, opterr, optopt; struct option { - const char* name; - int has_arg; - int* flag; - int val; + const char* name; + int has_arg; + int* flag; + int val; }; int getopt(int argc, char* const argv[], const char* optstring); -int getopt_long(int argc, char* const argv[], - const char* optstring, const struct option* longopts, int* longindex); +int getopt_long(int argc, + char* const argv[], + const char* optstring, + const struct option* longopts, + int* longindex); #if defined(__cplusplus) } diff --git a/src/mmap.c b/src/win32/mmap.c similarity index 61% rename from src/mmap.c rename to src/win32/mmap.c index b76e4ad64..d702a78f6 100644 --- a/src/mmap.c +++ b/src/win32/mmap.c @@ -5,35 +5,34 @@ #include "mmap.h" -void *mmap (void *addr, size_t len, int prot, int flags, int fd, long long offset) { - +void *mmap (void *addr, size_t len, int prot, int flags, int fd, long long offset) { void *buf; ssize_t count; - if ( addr || fd == -1 || (prot & PROT_WRITE)) return MAP_FAILED; + if ( addr || fd == -1 || (prot & PROT_WRITE)) { return(MAP_FAILED); } buf = malloc(len); - if ( NULL == buf ) return MAP_FAILED; - if (lseek(fd,offset,SEEK_SET) != offset) { + if ( NULL == buf ) { return(MAP_FAILED); } + + if (lseek(fd, offset, SEEK_SET) != offset) { free(buf); - return MAP_FAILED; + return(MAP_FAILED); } - count = read(fd, buf, len); if (count != (ssize_t)len) { free (buf); - return MAP_FAILED; + return(MAP_FAILED); } - return buf; + return(buf); (void)flags; } int munmap (void *addr, size_t len) { free (addr); - return 0; + return(0); (void)len; } diff --git a/src/win32/mmap.h b/src/win32/mmap.h new file mode 100644 index 000000000..1f2e756cb --- /dev/null +++ b/src/win32/mmap.h @@ -0,0 +1,29 @@ +#ifndef STLINK_MMAP_H +#define STLINK_MMAP_H + +#ifdef STLINK_HAVE_SYS_MMAN_H +#include +#else + +#define PROT_READ (1 << 0) +#define PROT_WRITE (1 << 1) + +#define MAP_SHARED (1 << 0) +#define MAP_PRIVATE (1 << 1) +#define MAP_ANONYMOUS (1 << 5) +#define MAP_FAILED ((void *)-1) + +#ifdef __cplusplus +extern "C" { +#endif + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, long long offset); +int munmap(void *addr, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_SYS_MMAN_H */ + +#endif /* STLINK_MMAP_H */ diff --git a/src/win32/unistd.h b/src/win32/unistd/unistd.h similarity index 73% rename from src/win32/unistd.h rename to src/win32/unistd/unistd.h index 5b2798b41..ac9d0add3 100644 --- a/src/win32/unistd.h +++ b/src/win32/unistd/unistd.h @@ -3,19 +3,23 @@ /* * This file intended to serve as a drop-in replacement for unistd.h on Windows - * Please add functionality as neeeded. + * Please add functionality as needed. */ #include #include + #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable: 4820) #endif + #include + #if defined(_MSC_VER) #pragma warning(pop) #endif + #include // getopt at: https://gist.github.com/ashelly/7776712 #include // for getpid() and the exec..() family #include // for _getcwd() and _chdir() @@ -39,27 +43,30 @@ #define chdir _chdir #define isatty _isatty #define lseek _lseek -/* read, write, and close are NOT being defined here, + +/* + * Read, write, and close are NOT being defined here, * because while there are file handle specific versions for Windows, they probably don't work for sockets. - * You need to look at your app and consider whether to call e.g. closesocket(). */ + * You need to look at your app and consider whether to call e.g. closesocket(). + */ #define ssize_t int -#define STDIN_FILENO 0 +#define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -/* should be in some equivalent to */ -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; +// should be in some equivalent to +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; #ifndef STLINK_HAVE_UNISTD_H int usleep(unsigned int waitTime); #endif -#endif /* unistd.h */ +#endif // _UNISTD_H diff --git a/src/win32/win32_socket.c b/src/win32/win32_socket.c new file mode 100644 index 000000000..9138a7679 --- /dev/null +++ b/src/win32/win32_socket.c @@ -0,0 +1,316 @@ +#if defined(_WIN32) + +#include "win32_socket.h" + +#undef socket +#undef connect +#undef accept +#undef shutdown + +#include +#include +#include + +int win32_poll(struct pollfd *fds, unsigned int nfds, int timo) { + struct timeval timeout, *toptr; + fd_set ifds, ofds, efds, *ip, *op; + unsigned int i; + int rc; + +#ifdef _MSC_VER +#pragma warning(disable: 4548) +#endif + + /* Set up the file-descriptor sets in ifds, ofds and efds. */ + FD_ZERO(&ifds); + FD_ZERO(&ofds); + FD_ZERO(&efds); + + for (i = 0, op = ip = 0; i < nfds; ++i) { + fds[i].revents = 0; + + if (fds[i].events & (POLLIN | POLLPRI)) { + ip = &ifds; + FD_SET(fds[i].fd, ip); + } + + if (fds[i].events & POLLOUT) { + op = &ofds; + FD_SET(fds[i].fd, op); + } + + FD_SET(fds[i].fd, &efds); + } + +#ifdef _MSC_VER +#pragma warning(default: 4548) +#endif + + /* Set up the timeval structure for the timeout parameter */ + if (timo < 0) { + toptr = 0; + } else { + toptr = &timeout; + timeout.tv_sec = timo / 1000; + timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000; + } + +#ifdef DEBUG_POLL + printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n", + (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op); +#endif + + rc = select(0, ip, op, &efds, toptr); + +#ifdef DEBUG_POLL + printf("Exiting select rc=%d\n", rc); +#endif + + if (rc <= 0) { return(rc); } + + if (rc > 0) { + for ( i = 0; i < nfds; ++i) { + int fd = fds[i].fd; + + if (fds[i].events & (POLLIN | POLLPRI) && FD_ISSET(fd, &ifds)) { + fds[i].revents |= POLLIN; + } + + if (fds[i].events & POLLOUT && FD_ISSET(fd, &ofds)) { + fds[i].revents |= POLLOUT; + } + + if (FD_ISSET(fd, &efds)) { + // Some error was detected ... should be some way to know + fds[i].revents |= POLLHUP; + } + +#ifdef DEBUG_POLL + printf("%d %d %d revent = %x\n", + FD_ISSET(fd, &ifds), + FD_ISSET(fd, &ofds), + FD_ISSET(fd, &efds), + fds[i].revents); +#endif + + } + } + + return(rc); +} + +static void set_connect_errno(int winsock_err) { + switch (winsock_err) { + case WSAEINVAL: + case WSAEALREADY: + case WSAEWOULDBLOCK: + errno = EINPROGRESS; + break; + default: + errno = winsock_err; + break; + } +} + +static void set_socket_errno(int winsock_err) { + switch (winsock_err) { + case WSAEWOULDBLOCK: + errno = EAGAIN; + break; + default: + errno = winsock_err; + break; + } +} + +/* A wrapper around the socket() function. + * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs, + * even if we are using winsock. + */ +SOCKET win32_socket(int domain, int type, int protocol) { + SOCKET fd = socket(domain, type, protocol); + + if (fd == INVALID_SOCKET) { set_socket_errno(WSAGetLastError()); } + + return(fd); +} + +/* A wrapper around the connect() function. + * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs, + * even if we are using winsock. + */ +int win32_connect(SOCKET fd, struct sockaddr *addr, socklen_t addr_len) { + int rc = connect(fd, addr, addr_len); + assert(rc == 0 || rc == SOCKET_ERROR); + + if (rc == SOCKET_ERROR) { set_connect_errno(WSAGetLastError()); } + + return(rc); +} + +/* A wrapper around the accept() function. + * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs, + * even if we are using winsock. + */ +SOCKET win32_accept(SOCKET fd, struct sockaddr *addr, socklen_t *addr_len) { + SOCKET newfd = accept(fd, addr, addr_len); + + if (newfd == INVALID_SOCKET) { + set_socket_errno(WSAGetLastError()); + newfd = (SOCKET)-1; + } + + return(newfd); +} + +/* A wrapper around the shutdown() function. + * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs, + * even if we are using winsock. + */ +int win32_shutdown(SOCKET fd, int mode) { + int rc = shutdown(fd, mode); + assert(rc == 0 || rc == SOCKET_ERROR); + + if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); } + + return(rc); +} + +int win32_close_socket(SOCKET fd) { + int rc = closesocket(fd); + + if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); } + + return(rc); +} + +ssize_t win32_write_socket(SOCKET fd, void *buf, int n) { + int rc = send(fd, buf, n, 0); + + if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); } + + return(rc); +} + +ssize_t win32_read_socket(SOCKET fd, void *buf, int n) { + int rc = recv(fd, buf, n, 0); + + if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); } + + return(rc); +} + + +char * win32_strtok_r(char *s, const char *delim, char **lasts) { + register char *spanp; + register int c, sc; + char *tok; + + + if (s == NULL && (s = *lasts) == NULL) { return (NULL); } + + // skip (span) leading delimiters (s += strspn(s, delim), sort of). +cont: + c = *s++; + + for (spanp = (char *)delim; (sc = *spanp++) != 0;) + if (c == sc) { goto cont; } + + + if (c == 0) { // no non-delimiter characters + *lasts = NULL; + return (NULL); + } + + tok = s - 1; + + /* Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for ( ; ;) { + c = *s++; + spanp = (char *)delim; + + do { + if ((sc = *spanp++) == c) { + if (c == 0) { + s = NULL; + } else { + s[-1] = 0; + } + + *lasts = s; + return(tok); + } + + } while (sc != 0); + } + + // NOT REACHED +} + +char *win32_strsep (char **stringp, const char *delim) { + register char *s; + register const char *spanp; + register int c, sc; + char *tok; + + if ((s = *stringp) == NULL) { + return(NULL); + } + + for (tok = s; ;) { + c = *s++; + spanp = delim; + + do { + if ((sc = *spanp++) == c) { + if (c == 0) { + s = NULL; + } else { + s[-1] = 0; + } + + *stringp = s; + return(tok); + } + + } while (sc != 0); + } + + // NOT REACHED +} + +#ifndef STLINK_HAVE_UNISTD_H +int usleep(unsigned int waitTime) { + if (waitTime >= 1000) { + /* Don't do long busy-waits. + * However much it seems like the QPC code would be more accurate, + * you can and probably will lose your time slice at any point during the wait, + * so we might as well voluntarily give up the CPU with a WaitForSingleObject. + */ + HANDLE timer; + LARGE_INTEGER dueTime; + dueTime.QuadPart = -10 * (LONGLONG)waitTime; + timer = CreateWaitableTimer(NULL, TRUE, NULL); + SetWaitableTimer(timer, &dueTime, 0, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); + + return(0); + } + + LARGE_INTEGER perf_cnt, start, now; + + QueryPerformanceFrequency(&perf_cnt); + QueryPerformanceCounter(&start); + + do { + QueryPerformanceCounter((LARGE_INTEGER*)&now); + } while ((now.QuadPart - start.QuadPart) / (float)perf_cnt.QuadPart * 1000 * 1000 < waitTime); + + return(0); +} +#endif + +#endif // defined(_WIN32) diff --git a/src/mingw/mingw.h b/src/win32/win32_socket.h similarity index 76% rename from src/mingw/mingw.h rename to src/win32/win32_socket.h index 8f5b992fe..5f8f09589 100644 --- a/src/mingw/mingw.h +++ b/src/win32/win32_socket.h @@ -1,4 +1,4 @@ -#if defined(__MINGW32__) || defined(_MSC_VER) +#if defined(_WIN32) #define _USE_W32_SOCKETS 1 @@ -9,19 +9,20 @@ #include #include + #if defined(_MSC_VER) #pragma comment(lib, "ws2_32.lib") #endif + #include #if defined(_MSC_VER) #pragma warning(pop) #endif -/* winsock doesn't feature poll(), so there is a version implemented - * in terms of select() in mingw.c. The following definitions - * are copied from linux man pages. A poll() macro is defined to - * call the version in mingw.c. +/* winsock doesn't feature poll(), so there is a version implemented in terms of select() in win32_socket.c. + * The following definitions are copied from linux man pages. + * A poll() macro is defined to call the version in win32_socket.c. */ #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) @@ -39,11 +40,10 @@ struct pollfd { #endif #define poll(x, y, z) win32_poll(x, y, z) -/* These wrappers do nothing special except set the global errno variable if - * an error occurs (winsock doesn't do this by default). They set errno - * to unix-like values (i.e. WSAEWOULDBLOCK is mapped to EAGAIN), so code - * outside of this file "shouldn't" have to worry about winsock specific error - * handling. +/* These wrappers do nothing special except set the global errno variable if an error occurs + * (winsock doesn't do this by default). + * They set errno to unix-like values (i.e. WSAEWOULDBLOCK is mapped to EAGAIN), + * so code outside of this file "shouldn't" have to worry about winsock specific error handling. */ #define socket(x, y, z) win32_socket(x, y, z) #define connect(x, y, z) win32_connect(x, y, z) @@ -62,8 +62,8 @@ SOCKET win32_accept(SOCKET, struct sockaddr*, socklen_t *); int win32_shutdown(SOCKET, int); int win32_close_socket(SOCKET fd); -#define strtok_r(x, y, z) win32_strtok_r(x, y, z) -#define strsep(x,y) win32_strsep(x,y) +#define strtok_r(x, y, z) win32_strtok_r(x, y, z) +#define strsep(x,y) win32_strsep(x,y) char *win32_strtok_r(char *s, const char *delim, char **lasts); char *win32_strsep(char **stringp, const char *delim); @@ -71,4 +71,4 @@ char *win32_strsep(char **stringp, const char *delim); ssize_t win32_read_socket(SOCKET fd, void *buf, int n); ssize_t win32_write_socket(SOCKET fd, void *buf, int n); -#endif //defined(__MINGW32__) || defined(_MSC_VER) +#endif // defined(_WIN32) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6e60fdd5a..a3011fc7e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,6 +11,6 @@ foreach (test ${TESTEXEC}) add_test(test-${test} ${CMAKE_BINARY_DIR}/bin/test-${test}) endforeach () -add_executable(test-flash flash.c "${CMAKE_SOURCE_DIR}/src/tools/flash_opts.c") +add_executable(test-flash flash.c "${CMAKE_SOURCE_DIR}/src/st-flash/flash_opts.c") target_link_libraries(test-flash ${STLINK_LIB_SHARED} ${SSP_LIB}) add_test(test-flash ${CMAKE_BINARY_DIR}/bin/test-flash) diff --git a/tests/flash.c b/tests/flash.c index d47b3564d..a8d479b2d 100644 --- a/tests/flash.c +++ b/tests/flash.c @@ -6,7 +6,7 @@ #include #if defined(_MSC_VER) - #include +#include #endif struct Test { @@ -37,25 +37,25 @@ static bool execute_test(const struct Test * test) { /* parse (tokenize) the test command line */ #if defined(_MSC_VER) - char *cmd_line = alloca(strlen(test->cmd_line) + 1); + char *cmd_line = alloca(strlen(test->cmd_line) + 1); #else - char cmd_line[strlen(test->cmd_line) + 1]; + char cmd_line[strlen(test->cmd_line) + 1]; #endif strcpy(cmd_line, test->cmd_line); for (char * tok = strtok(cmd_line, " "); tok; tok = strtok(NULL, " ")) { - if ((size_t)ac >= sizeof(av)/sizeof(av[0])) - return false; + if ((size_t)ac >= sizeof(av) / sizeof(av[0])) return(false); + av[ac] = tok; ++ac; } - /* call */ + /* Call */ struct flash_opts opts; int res = flash_get_opts(&opts, ac, av); - /* compare results */ + /* Compare results */ bool ret = (res == test->res); if (ret && (res == 0)) { @@ -71,87 +71,87 @@ static bool execute_test(const struct Test * test) { } printf("[%s] (%d) %s\n", ret ? "OK" : "ERROR", res, test->cmd_line); - return ret; + return(ret); } static struct Test tests[] = { { "", -1, FLASH_OPTS_INITIALIZER }, { "--debug --reset read test.bin 0x80000000 0x1000", 0, - { .cmd = FLASH_CMD_READ, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0x1000, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_READ, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0x1000, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } }, { "--debug --reset write test.bin 0x80000000", 0, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } }, { "--debug --freq 5k --reset write test.bin 0x80000000", 0, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 5, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 5, + .format = FLASH_FORMAT_BINARY } }, { "--debug --freq 15K --reset write test.bin 0x80000000", 0, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 15, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 15, + .format = FLASH_FORMAT_BINARY } }, { "--debug --freq=5k --reset write test.bin 0x80000000", 0, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 5, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 5, + .format = FLASH_FORMAT_BINARY } }, { "--debug --freq=6k --reset write test.bin 0x80000000", -1, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 6, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 6, + .format = FLASH_FORMAT_BINARY } }, { "--debug --reset read test.bin 0x80000000 1000", 0, - { .cmd = FLASH_CMD_READ, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 1000, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_READ, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 1000, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } }, { "--debug --reset read test.bin 0x80000000 1k", 0, { .cmd = FLASH_CMD_READ, @@ -176,71 +176,72 @@ static struct Test tests[] = { .format = FLASH_FORMAT_BINARY } }, { "--debug --reset write test.bin 0x80000000", 0, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.bin", - .addr = 0x80000000, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } }, { "erase", 0, - { .cmd = FLASH_CMD_ERASE, - .serial = { 0 }, - .filename = NULL, - .addr = 0, - .size = 0, - .reset = 0, - .log_level = STND_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_ERASE, + .serial = { 0 }, + .filename = NULL, + .addr = 0, + .size = 0, + .reset = 0, + .log_level = STND_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } }, { "--debug --reset --format=ihex write test.hex", 0, - { .cmd = FLASH_CMD_WRITE, - .serial = { 0 }, - .filename = "test.hex", - .addr = 0, - .size = 0, - .reset = 1, - .log_level = DEBUG_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_IHEX } + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.hex", + .addr = 0, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_IHEX } }, { "--debug --reset --format=binary write test.hex", -1, FLASH_OPTS_INITIALIZER }, { "--debug --reset --format=ihex write test.hex 0x80000000", -1, FLASH_OPTS_INITIALIZER }, { "--debug --reset write test.hex sometext", -1, FLASH_OPTS_INITIALIZER }, { "--serial A1020304 erase sometext", -1, FLASH_OPTS_INITIALIZER }, { "--serial A1020304 erase", 0, - { .cmd = FLASH_CMD_ERASE, - .serial = "\xA1\x02\x03\x04", - .filename = NULL, - .addr = 0, - .size = 0, - .reset = 0, - .log_level = STND_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_ERASE, + .serial = "\xA1\x02\x03\x04", + .filename = NULL, + .addr = 0, + .size = 0, + .reset = 0, + .log_level = STND_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } }, { "--serial=A1020304 erase", 0, - { .cmd = FLASH_CMD_ERASE, - .serial = "\xA1\x02\x03\x04", - .filename = NULL, - .addr = 0, - .size = 0, - .reset = 0, - .log_level = STND_LOG_LEVEL, - .freq = 0, - .format = FLASH_FORMAT_BINARY } + { .cmd = FLASH_CMD_ERASE, + .serial = "\xA1\x02\x03\x04", + .filename = NULL, + .addr = 0, + .size = 0, + .reset = 0, + .log_level = STND_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } }, }; int main() { bool allOk = true; - for (size_t i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) { + + for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) if (!execute_test(&tests[i])) allOk = false; - } + return (allOk ? 0 : 1); } diff --git a/tests/sg.c b/tests/sg.c index 1af177174..745df845f 100644 --- a/tests/sg.c +++ b/tests/sg.c @@ -1,9 +1,3 @@ -/* - * File: test_main.c - * - * main() ripped out of old stlink-hw.c - */ - #include #include #include @@ -11,7 +5,7 @@ #include #if defined(_MSC_VER) - #define __attribute__(x) +#define __attribute__(x) #endif static void __attribute__((unused)) mark_buf(stlink_t *sl) { @@ -30,28 +24,28 @@ static void __attribute__((unused)) mark_buf(stlink_t *sl) { } -int main(void) { +int main(void) { // main() ripped out of old stlink-hw.c /* Avoid unused parameter warning */ // set scpi lib debug level: 0 for no debug info, 10 for lots fputs( - "\nUsage: stlink-access-test [anything at all] ...\n" - "\n*** Notice: The stlink firmware violates the USB standard.\n" - "*** Because we just use libusb, we can just tell the kernel's\n" - "*** driver to simply ignore the device...\n" - "*** Unplug the stlink and execute once as root:\n" - "modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i\n\n", - stderr); + "\nUsage: stlink-access-test [anything at all] ...\n" + "\n*** Notice: The stlink firmware violates the USB standard.\n" + "*** Because we just use libusb, we can just tell the kernel's\n" + "*** driver to simply ignore the device...\n" + "*** Unplug the stlink and execute once as root:\n" + "modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i\n\n", + stderr); stlink_t *sl = stlink_v1_open(99, 1); - if (sl == NULL) - return 0; + + if (sl == NULL) return(0); // we are in mass mode, go to swd stlink_enter_swd_mode(sl); stlink_current_mode(sl); stlink_core_id(sl); stlink_status(sl); - //stlink_force_debug(sl); + // stlink_force_debug(sl); stlink_reset(sl); stlink_status(sl); // core system control block @@ -75,8 +69,8 @@ int main(void) { #define GPIOC 0x40011000 // port C #define GPIOC_CRH (GPIOC + 0x04) // port configuration register high #define GPIOC_ODR (GPIOC + 0x0c) // port output data register - #define LED_BLUE (1<<8) // pin 8 - #define LED_GREEN (1<<9) // pin 9 + #define LED_BLUE (1 << 8) // pin 8 + #define LED_GREEN (1 << 9) // pin 9 stlink_read_mem32(sl, GPIOC_CRH, 4); uint32_t io_conf = read_uint32(sl->q_buf, 0); DLOG("GPIOC_CRH = 0x%08x\n", io_conf); @@ -86,17 +80,19 @@ int main(void) { stlink_write_mem32(sl, GPIOC_CRH, 4); memset(sl->q_buf, 0, sizeof(sl->q_buf)); + for (int i = 0; i < 100; i++) { write_uint32(sl->q_buf, LED_BLUE | LED_GREEN); stlink_write_mem32(sl, GPIOC_ODR, 4); - //stlink_read_mem32(sl, 0x4001100c, 4); - //DD(sl, "GPIOC_ODR = 0x%08x", read_uint32(sl->q_buf, 0)); + // stlink_read_mem32(sl, 0x4001100c, 4); + // DD(sl, "GPIOC_ODR = 0x%08x", read_uint32(sl->q_buf, 0)); usleep(100 * 1000); memset(sl->q_buf, 0, sizeof(sl->q_buf)); stlink_write_mem32(sl, GPIOC_ODR, 4); // PC lo usleep(100 * 1000); } + write_uint32(sl->q_buf, io_conf); // set old state #endif @@ -104,10 +100,10 @@ int main(void) { // TODO rtfm: stlink doesn't have flash write routines // writing to the flash area confuses the fw for the next read access - //stlink_read_mem32(sl, 0, 1024*6); + // stlink_read_mem32(sl, 0, 1024*6); // flash 0x08000000 128kB fputs("++++++++++ read a flash at 0x0800 0000\n", stderr); - stlink_read_mem32(sl, 0x08000000, 1024 * 6); //max 6kB + stlink_read_mem32(sl, 0x08000000, 1024 * 6); // max 6kB clear_buf(sl); stlink_read_mem32(sl, 0x08000c00, 5); stlink_read_mem32(sl, 0x08000c00, 4); @@ -122,9 +118,9 @@ int main(void) { fputs("\n++++++++++ read/write 8bit, sram at 0x2000 0000 ++++++++++++++++\n\n", stderr); memset(sl->q_buf, 0, sizeof(sl->q_buf)); mark_buf(sl); - //stlink_write_mem8(sl, 0x20000000, 16); - //stlink_write_mem8(sl, 0x20000000, 1); - //stlink_write_mem8(sl, 0x20000001, 1); + // stlink_write_mem8(sl, 0x20000000, 16); + // stlink_write_mem8(sl, 0x20000000, 1); + // stlink_write_mem8(sl, 0x20000001, 1); stlink_write_mem8(sl, 0x2000000b, 3); stlink_read_mem32(sl, 0x20000000, 16); #endif @@ -157,7 +153,7 @@ int main(void) { stlink_read_mem32(sl, 0x20000000, 64); mark_buf(sl); - stlink_write_mem32(sl, 0x20000000, 1024 * 8); //8kB + stlink_write_mem32(sl, 0x20000000, 1024 * 8); // 8kB stlink_read_mem32(sl, 0x20000000, 1024 * 6); stlink_read_mem32(sl, 0x20000000 + 1024 * 6, 1024 * 2); #endif @@ -208,7 +204,7 @@ int main(void) { stlink_close(sl); #endif - //fflush(stderr); - //fflush(stdout); - return EXIT_SUCCESS; + // fflush(stderr); + // fflush(stdout); + return(EXIT_SUCCESS); } diff --git a/tests/usb.c b/tests/usb.c index ce72e24a5..03c135f00 100644 --- a/tests/usb.c +++ b/tests/usb.c @@ -3,14 +3,12 @@ #include #include -static void usage(void) -{ +static void usage(void) { puts("test-usb --reset"); puts("test-usb --no-reset"); } int main(int ac, char** av) { - stlink_t* sl; struct stlink_reg regs; int reset = 0; @@ -18,15 +16,18 @@ int main(int ac, char** av) { if (ac == 2) { if (strcmp(av[1], "--reset") == 0) reset = 2; - if (strcmp(av[1], "--no-reset") == 0) + + if (strcmp(av[1], "--no-reset") == 0) reset = 1; } + if (reset == 0) { usage(); - return 0; + return(0); } sl = stlink_open_usb(10, reset, NULL, 0); + if (sl != NULL) { printf("-- version\n"); stlink_version(sl); @@ -47,6 +48,7 @@ int main(int ac, char** av) { printf("-- core_id: %#x\n", sl->core_id); cortex_m3_cpuid_t cpuid; + if (stlink_cpu_id(sl, &cpuid)) { printf("Failed reading stlink_cpu_id\n"); } else { @@ -57,6 +59,7 @@ int main(int ac, char** av) { printf("-- read_sram\n"); static const uint32_t sram_base = STM32_SRAM_BASE; uint32_t off; + for (off = 0; off < 16; off += 4) stlink_read_mem32(sl, sram_base + off, 4); @@ -64,24 +67,24 @@ int main(int ac, char** av) { stlink_read_mem32(sl, STLINK_REG_CM3_FP_CTRL, 4); // no idea what reg this is... - //stlink_read_mem32(sl, 0xe000ed90, 4); + // stlink_read_mem32(sl, 0xe000ed90, 4); // no idea what register this is... - //stlink_read_mem32(sl, 0xe000edf0, 4); + // stlink_read_mem32(sl, 0xe000edf0, 4); // offset 0xC into TIM11 register? TIMx_DIER? - //stlink_read_mem32(sl, 0x4001100c, 4); + // stlink_read_mem32(sl, 0x4001100c, 4); - /* Test 32 bit Write */ - write_uint32(sl->q_buf,0x01234567); - stlink_write_mem32(sl,0x200000a8,4); - write_uint32(sl->q_buf,0x89abcdef); - stlink_write_mem32(sl,0x200000ac, 4); + /* Test 32 bit write */ + write_uint32(sl->q_buf, 0x01234567); + stlink_write_mem32(sl, 0x200000a8, 4); + write_uint32(sl->q_buf, 0x89abcdef); + stlink_write_mem32(sl, 0x200000ac, 4); stlink_read_mem32(sl, 0x200000a8, 4); stlink_read_mem32(sl, 0x200000ac, 4); /* Test 8 bit write */ - write_uint32(sl->q_buf,0x01234567); - stlink_write_mem8(sl,0x200001a8,3); - write_uint32(sl->q_buf,0x89abcdef); + write_uint32(sl->q_buf, 0x01234567); + stlink_write_mem8(sl, 0x200001a8, 3); + write_uint32(sl->q_buf, 0x89abcdef); stlink_write_mem8(sl, 0x200001ac, 3); stlink_read_mem32(sl, 0x200001a8, 4); stlink_read_mem32(sl, 0x200001ac, 4); @@ -96,8 +99,8 @@ int main(int ac, char** av) { stlink_write_reg(sl, 0x01234567, 3); stlink_write_reg(sl, 0x89abcdef, 4); stlink_write_reg(sl, 0x12345678, 15); - for (off = 0; off < 21; off += 1) - stlink_read_reg(sl, off, ®s); + + for (off = 0; off < 21; off += 1) stlink_read_reg(sl, off, ®s); stlink_read_all_regs(sl, ®s); @@ -115,5 +118,6 @@ int main(int ac, char** av) { stlink_close(sl); } - return 0; + + return(0); }