Merge branch 'develop' into debian

pull/1004/head
nightwalker-87 2020-07-06 01:33:49 +02:00 zatwierdzone przez GitHub
commit eb386ba84b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
77 zmienionych plików z 9595 dodań i 6445 usunięć

Wyświetl plik

@ -1,38 +0,0 @@
---
name: Bug Report (only valid if template is reused!)
about: 'Please read #906 before submitting a ticket.'
title: "[STM32 device name]: [Title]"
labels: ''
assignees: ''
---
Thank you for giving feedback to the stlink project.
In order to allow developers and other contributors to isolate and target your respective issue, please take some time to fill out each of the following items appropriate to your specific problem:
- Programmer/board type: [enter here] (e.g Stlink /v1, /v2, /v2-clone, /v2-1)
- Programmer firmware version: [enter here] (e.g STSW-LINK007 2.27.15)
- Operating system and version: [enter here] (e.g Linux, Mac OS X, Windows)
- **Stlink tools version** and/or git commit hash: [enter here] (e.g v1.1.0/git-c722056)
- Stlink commandline tool name: [enter here] (e.g `st-info`, `st-flash`, `st-util`)
- Target chip (and board if applicable): [enter here] (e.g STM32F402VG)
Futher we kindly ask you to describe the detected problem as detailed as possible and to add debug output if available, by using the following template:
Commandline-Output:
```
OUTPUT/ERROR of the commandline tool(s)
```
Expected/description:
`short description of the expected value`
**NOTICE: This bug report may be closed without further notice, if not enough information is provided!**
Thank you for your support.
The stlink project maintainers

2
.gitignore vendored
Wyświetl plik

@ -1,5 +1,5 @@
build
build-mingw
.project
obj-*
*.user*
.project

Wyświetl plik

@ -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
###
@ -31,15 +32,6 @@ else ()
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
endif ()
## Set installation directories for header files ### TODO: Clean this up...
if (IS_DIRECTORY ${INCLUDE_INSTALL_DIR})
set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_DIR} CACHE PATH "Main include directory")
set(STLINK_INCLUDE_PATH "${INCLUDE_INSTALL_DIR}")
else ()
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "Main include directory")
set(STLINK_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}")
endif ()
###
# Dependencies
@ -47,33 +39,35 @@ endif ()
find_package(libusb REQUIRED)
## Package configuration (pkg-config) on unix-based systems
if (NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
#add_subdirectory(cmake/pkgconfig)
find_package(PkgConfig)
pkg_check_modules(GTK3 gtk+-3.0)
endif ()
## 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)
set(SSP_LIB -static ssp)
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 ()
@ -84,57 +78,60 @@ 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 installation directory for header files
set(STLINK_INCLUDE_PATH ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} CACHE PATH "Main include install directory")
## Subordinate CMakeLists for version config & header installation
#add_subdirectory(inc)
add_subdirectory(inc)
## Define source- and headerfiles for stlink library
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
inc/stlink.h
src/stlink-lib/commands.h
src/stlink-lib/libusb_settings.h
src/stlink-lib/reg.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
@ -231,15 +228,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)
@ -277,11 +277,6 @@ endif ()
# Additional build tasks
###
# ====
add_subdirectory(include) # contains subordinate CMakeLists for version config and old header includes
### TODO: Clean this up ...
# ====
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

Wyświetl plik

@ -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")

Wyświetl plik

@ -52,10 +52,10 @@ if (GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
# ...the version does not match with git-version string
if (NOT __version_str STREQUAL __version_file)
message(STATUS "Rewrite ${PROJECT_SOURCE_DIR}/.version with ${__version_str}.")
message(STATUS "Rewrite ${PROJECT_SOURCE_DIR}/.version with ${__version_str}!")
endif ()
else (EXISTS "${PROJECT_SOURCE_DIR}/.version")
else (NOT EXISTS "${PROJECT_SOURCE_DIR}/.version")
# No local .version file found: Create a new one...
file(WRITE "${PROJECT_SOURCE_DIR}/.version" ${__version_str})

Wyświetl plik

@ -12,6 +12,7 @@ set(CPACK_PACKAGE_VENDOR "stlink-org")
set(CMAKE_PROJECT_HOMEPAGE_URL "https://github.com/stlink-org/stlink")
set(CPACK_SET_DESTDIR "ON")
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/dist)
set(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_BINARY_DIR}/dist")
if (APPLE) # macOS

Wyświetl plik

@ -1,4 +1,4 @@
stlink (1.6.1+ds-1) unstable; urgency=medium
stlink (1.6.1) unstable; urgency=medium
* Initial cpack-based package release for Debian/Ubuntu

3090
config/code_style.cfg 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -88,7 +88,6 @@ Install the following packages from your package repository:
* `build-essential` (on Debian based distros (Debian, Ubuntu))
* `cmake` (3.4.2 or later, use the latest version available from the repository)
* `rpm` (on Debian based distros (Debian, Ubuntu), needed for package build with `make package`)
* `pkg-config`
* `libusb-1.0`
* `libusb-1.0-0-dev` (development headers for building)
* `libgtk-3-dev` (_optional_, needed for `stlink-gui`)
@ -194,7 +193,6 @@ Then install the following dependencies from the package repository:
* `git`
* `gcc` or `llvm` (for clang) (C-compiler)
* `cmake`
* `pkg-config`
* `libusb`
* `gtk+3` or `gtk3` (_optional_, needed for `stlink-gui`)

Wyświetl plik

@ -1,4 +1,16 @@
=== Compilation with pkg-config ===
In order to use pkg-config for development purposes, add the following lines to the toplevel CMakeLists.txt file:
###
# Additional build tasks
###
## Package configuration (pkg-config) on unix-based systems
if (NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
add_subdirectory(doc/dev/pkg-config) # external tool pkg-config
endif ()
=== Target Identification ===
The following information is available about the target:
@ -42,7 +54,7 @@ Include stlink/backend.h
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;
Descriptions below describe the actions of the usb.h backend:
@ -55,7 +67,7 @@ int (*exit_debug_mode) (stlink_t * sl);
int (*enter_swd_mode) (stlink_t * sl);
_stlink_usb_enter_swd_mode: Send STLINK_DEBUG_ENTER+STLINK_DEBUG_ENTER_SWD
returns -1 or 0
int (*enter_jtag_mode) (stlink_t * stl);
int (*exit_dfu_mode) (stlink_t * stl);
@ -65,19 +77,19 @@ int (*exit_dfu_mode) (stlink_t * stl);
int (*core_id) (stlink_t * stl);
_stlink_usb_core_id: Assign the result from STLINK_DEBUG_READCOREID to stl->core_id
returns -1 or 0
int (*reset) (stlink_t * stl);
_stlink_usb_reset: Send STLINK_DEBUG_RESETSYS and reset via AIRCR
AIRCR is part of the CMSIS System Control Block (SCB), which is located in
AIRCR is part of the CMSIS System Control Block (SCB), which is located in
the System Control Space at 0xE000ED0C
returns -1 or 0 ?
int (*jtag_reset) (stlink_t * stl, int value);
_stlink_usb_jtag_reset: Send STLINK_JTAG_DRIVE_NRST.
"value" is sent as argument for STLINK_JTAG_DRIVE_NRST and probably contains
the status of the NRST line (0: low, 1: high). Also the value 2 is used in the software.
returns -1 or 0
int (*run) (stlink_t * stl);
_stlink_usb_run: Send STLINK_DEBUG_RUNCORE
returns -1 or 0
@ -85,12 +97,12 @@ int (*run) (stlink_t * stl);
int (*status) (stlink_t * stl);
_stlink_usb_status: Assign the result from STLINK_DEBUG_GETSTATUS to stl->q_len
returns -1 or 0
int (*version) (stlink_t *sl);
_stlink_usb_version: Read version with STLINK_GET_VERSION.
Result is stored in sl->q_buf (6 bytes????)
returns -1 or 0
int (*read_debug32) (stlink_t *sl, uint32_t addr, uint32_t *data);
_stlink_usb_read_debug32: Send STLINK_JTAG_READDEBUG_32BIT
to read 32 bits from "addr". The result data is stored at "*data".
@ -99,10 +111,10 @@ int (*read_debug32) (stlink_t *sl, uint32_t addr, uint32_t *data);
int (*read_mem32) (stlink_t *sl, uint32_t addr, uint16_t len);
_stlink_usb_read_mem32: Use STLINK_DEBUG_READMEM_32BIT
to read "len" bytes from "addr"
Result is returned in sl->q_buf, sl->q_len returns the size of the data (should be
Result is returned in sl->q_buf, sl->q_len returns the size of the data (should be
equal to "len"???).
returns -1 or 0
int (*write_debug32) (stlink_t *sl, uint32_t addr, uint32_t data);
_stlink_usb_write_debug32: Use STLINK_JTAG_WRITEDEBUG_32BIT
to store "data" at "addr"
@ -124,13 +136,13 @@ int (*read_all_regs) (stlink_t *sl, struct stlink_reg * regp);
_stlink_usb_read_all_regs: Send STLINK_DEBUG_READALLREGS to read
all register values and store them into *regp;
returns -1 or 0
int (*read_reg) (stlink_t *sl, int r_idx, struct stlink_reg * regp);
_stlink_usb_read_reg: Send STLINK_DEBUG_READREG to read specific register "r_idx".
The result is then stored in *regp in the correct register.
The result is then stored in *regp in the correct register.
Example if "r_idx" is 18, then the result is stored in regp->process_sp
returns -1 or 0
int (*read_all_unsupported_regs) (stlink_t *sl, struct stlink_reg *regp);
_stlink_usb_read_all_unsupported_regs: Calls "_stlink_usb_read_unsupported_reg"
(see below) to read all registers.
@ -142,7 +154,7 @@ int (*read_unsupported_reg) (stlink_t *sl, int r_idx, struct stlink_reg *regp);
Also will fill regp->s (???) for some specific "r_idx" values.
WARNING: Some r_idx values may lead to a out of array bound problem in C.
returns -1 or 0
int (*write_unsupported_reg) (stlink_t *sl, uint32_t value, int idx, struct stlink_reg *regp);
_stlink_usb_write_unsupported_reg:
Updates one of the following registers:
@ -154,14 +166,14 @@ int (*write_unsupported_reg) (stlink_t *sl, uint32_t value, int idx, struct stli
returns -1 or 0
int (*write_reg) (stlink_t *sl, uint32_t reg, int idx);
_stlink_usb_write_reg: Use STLINK_DEBUG_WRITEREG to update register "idx"
_stlink_usb_write_reg: Use STLINK_DEBUG_WRITEREG to update register "idx"
with value "reg".
returns -1 or 0
int (*step) (stlink_t * stl);
_stlink_usb_step: Send STLINK_DEBUG_STEPCORE
returns -1 or 0
int (*current_mode) (stlink_t * stl);
_stlink_usb_current_mode: Send STLINK_GET_CURRENT_MODE and return
the current mode.
@ -174,15 +186,15 @@ int (*current_mode) (stlink_t * stl);
int (*force_debug) (stlink_t *sl);
_stlink_usb_force_debug: Sends STLINK_DEBUG_FORCEDEBUG. No other side effects
returns -1 or 0
int32_t (*target_voltage) (stlink_t *sl);
_stlink_usb_target_voltage: Send STLINK_GET_TARGET_VOLTAGE
returns -1 or the target voltage. (??? dimension is not clear...)
int (*set_swdclk) (stlink_t * stl, uint16_t divisor);
int (*set_swdclk) (stlink_t * stl, uint16_t divisor);
_stlink_usb_set_swdclk: Send STLINK_DEBUG_APIV2_SWD_SET_FREQ and "divisor" value
returns -1 or 0
=== Other Functions ===
@ -193,17 +205,17 @@ Include: stlink.h
Prototype: void stlink_close(stlink_t *sl);
Include: inc/stlink.h
Definition: src/common.c
Description:
Description:
Calls the backend "close" procedure and frees 'sl'
Backend: "close"
Arguments:
sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb()
Return: -
Include: inc/stlink.h
Prototype: int stlink_core_id(stlink_t *sl);
Definition: src/common.c
Description:
Description:
Calls the backend "core_id", calls stlink_print_data() on higher verbose levels.
Assigns the core id returned by STLINK_DEBUGREADCOREID to sl->core_id
Only some specific core ids are used: See include/stm32.h
@ -216,8 +228,8 @@ Return: -1 for error. 0 for success.
Include: inc/stlink.h
Prototype: int stlink_reset(stlink_t *sl);
Definition: src/common.c
Description:
Just calls the backend "reset" procedure (reset via STLINK_DEBUG_RESETSYS
Description:
Just calls the backend "reset" procedure (reset via STLINK_DEBUG_RESETSYS
and reset via AIRCR register at 0xE000ED0C)
Backend: "reset"
Arguments:
@ -227,29 +239,29 @@ Return: -1 for error. 0 for success.
Include: inc/stlink.h
Prototype: int stlink_jtag_reset(stlink_t *sl, int value);
Definition: src/common.c
Description:
Just calls the backend "jtag_reset" procedure
Description:
Just calls the backend "jtag_reset" procedure
Backend: "jtag_reset"
Arguments:
sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb()
value: 0: drive low, 1: drive high, 2: ????
Return: -1 for error. 0 for success.
Include: inc/stlink.h
Prototype: int stlink_run(stlink_t *sl);
Definition: src/common.c
Description:
Description:
Just calls the backend "run" procedure.
Backend: "run"
Arguments:
sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb()
Return: -1 for error. 0 for success.
Include: inc/stlink.h
Prototype: int stlink_status(stlink_t *sl);
Definition: src/common.c
Description:
Description:
Calls the backend "status" procedure and the procedure "stlink_core_stat()" to
store the status in "sl->core_stat". Possible value for "sl->core_stat" are:
STLINK_CORE_RUNNING
@ -259,12 +271,12 @@ Backend: "status"
Arguments:
sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb()
Return: -1 for error. 0 for success.
Include: inc/stlink.h
Prototype: int stlink_version(stlink_t *sl);
Definition: src/common.c
Description:
Description:
Calls the backend "version" procedure, parses the result and puts the result into sl->version
This version probably refers to the version of the adapter.
Backend: "version"
@ -272,9 +284,9 @@ Arguments:
sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb()
Return: -1 for error. 0 for success.
int stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data);
int stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len);
int stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len);
int stlink_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data);
int stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len);
int stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len);
@ -305,9 +317,9 @@ Return: -1 for error. 0 for success.
Include: inc/stlink.h
Prototype: int stlink_chip_id(stlink_t *sl, uint32_t *chip_id);
Definition: src/common.c
Description:
Description:
Tries to read out the chip id via memory read from the device.
Note: sl->chip_id is NOT updated by this procedure. Instead this happens in stlink_load_device_params():
Note: sl->chip_id is NOT updated by this procedure. Instead this happens in stlink_load_device_params():
Do not call this function, but instead call stlink_load_device_params()
Backend: -
Arguments:
@ -319,7 +331,7 @@ Return: -1 for error. 0 for success.
Include: inc/stlink.h
Prototype: int stlink_cpu_id(stlink_t *sl, cortex_m3_cpuid_t *cpuid);
Definition: src/common.c
Description:
Description:
Reads the CPU id from STLINK_REG_CM3_CPUID (0xE000ED00, first value of
the SCB, system control block) and splits this into
cpuid->implementer_id
@ -333,19 +345,19 @@ Arguments:
cpuid: Pointer. Result is stored via this pointer.
Return: -1 for error. 0 for success.
int stlink_erase_flash_page(stlink_t* sl, stm32_addr_t flashaddr);
uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr);
uint16_t read_uint16(const unsigned char *c, const int pt);
void stlink_core_stat(stlink_t *sl);
Include: inc/stlink.h
Prototype: void stlink_print_data(stlink_t *sl);
Definition: src/common.c
Description:
Description:
If debug logging is enabled: Print the HEX content of the q_buf array.
q_buf will contain the result of the last "backend" command.
Backend: -
@ -362,21 +374,21 @@ Return: -
int write_buffer_to_sram(stlink_t *sl, flash_loader_t* fl, const uint8_t* buf, size_t size);
int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size);
int stlink_fread(stlink_t* sl, const char* path, bool is_ihex, stm32_addr_t addr, size_t size);
Include: inc/stlink.h
Prototype: int stlink_load_device_params(stlink_t *sl);
Definition: src/common.c
Description:
Description:
This is one of the most important procedures. It will get all the device info
and store the results in the "sl" structure. Many other procedures will depend
on this information.
The identification is based on the stlink_chip_id() result and the flash_size register value
The identification is based on the stlink_chip_id() result and the flash_size register value
Backend: -
Arguments:
sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb()
Return: -1 for error. 0 for success.
int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte);
int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t* option_byte);

Wyświetl plik

@ -8,6 +8,7 @@ stlink Tools Tutorial
| --flash=n[k][m] | st-flash | One can specify `--flash=128k` for example, to override the default value of 64k<br />for the STM32F103C8T6 to assume 128k of flash being present. This option accepts<br />decimal (128k), octal 0200k, or hex 0x80k values. Leaving the multiplier out is<br />equally valid, e.g.: `--flash=0x20000`. The size may be followed by an optional "k"<br />or "m" to multiply the given value by 1k (1024) or 1M respectively. | v1.4.0 |
| --freq=n[k][m] | st-flash,<br />st-util | The frequency of the SWD/JTAG interface can be specified, to override the default<br />1800 kHz configuration. This option solely accepts decimal values (5K or 1.8M) with<br />the unit `Hz` being left out. Valid frequencies are `5K, 15K, 25K, 50K, 100K,`<br />`125K, 240K, 480K, 950K, 1200K(1.2M), 1800K(1.8M), 4000K(4M)`. | v1.6.1 |
| --opt | st-flash | Optimisation can be enabled in order to skip flashing empty (0x00 or 0xff) bytes at<br />the end of binary file. This may cause some garbage data left after a flash operation.<br />This option was enabled by default in earlier releases. | v1.6.1 |
| --reset | st-flash | Trigger a reset both before and after flashing. | v1.0.0 |
| --version | st-info,<br />st-flash,<br />st-util | Print version information. | |
| --help | st-flash,<br />st-util | Print list of available commands. _(To be added to this table.)_ | |

Wyświetl plik

@ -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
}
}

10
inc/CMakeLists.txt 100644
Wyświetl plik

@ -0,0 +1,10 @@
configure_file(
"${PROJECT_SOURCE_DIR}/inc/version.h.in"
"${CMAKE_BINARY_DIR}/inc/version.h"
)
file(GLOB STLINK_HEADERS
"${CMAKE_SOURCE_DIR}/inc/*.h"
"${CMAKE_SOURCE_DIR}/src/stlink-lib/*.h"
"${CMAKE_BINARY_DIR}/inc/version.h")
install(FILES ${STLINK_HEADERS} DESTINATION ${STLINK_INCLUDE_PATH})

Wyświetl plik

@ -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_

Wyświetl plik

@ -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 <backend.h>
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

Wyświetl plik

@ -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

Wyświetl plik

@ -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_

Wyświetl plik

@ -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)

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -1,637 +0,0 @@
#include <stlink.h>
#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;
}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,392 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stlink.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;
/* 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;
}

Wyświetl plik

@ -1,206 +0,0 @@
#include <stddef.h>
#include <string.h>
#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;
}

340
src/md5.c
Wyświetl plik

@ -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 <memory.h>
#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 );
}

100
src/md5.h
Wyświetl plik

@ -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 <stdint.h>
#include <stdio.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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]
);

Wyświetl plik

@ -1,309 +0,0 @@
#if defined(__MINGW32__) || defined(_MSC_VER)
#include "mingw.h"
#undef socket
#undef connect
#undef accept
#undef shutdown
#include <string.h>
#include <errno.h>
#include <assert.h>
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

Wyświetl plik

@ -1,31 +0,0 @@
#ifndef STLINK_MMAP_H
#define STLINK_MMAP_H
#ifdef STLINK_HAVE_SYS_MMAN_H
#include <sys/mman.h>
#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 */

Wyświetl plik

@ -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 <stlink.h>
#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 */

Wyświetl plik

@ -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 <sys/types.h>
#include <stlink.h>
#include <flash.h>
#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 <serial>] [--format <format>] [--flash=<fsize>] [--freq=<Hz>] {read|write} <path> [addr] [size]");
puts("command line: ./st-flash [--debug] [--freq=<Hz>] [--serial <serial>] erase");
puts("command line: ./st-flash [--debug] [--freq=<Hz>] [--serial <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);
}

Wyświetl plik

@ -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;
};

Wyświetl plik

@ -0,0 +1,341 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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 <path> <addr> <size>")); }
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 <path> <addr>")); }
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 <path>")); }
o->filename = av[0];
} else {
return(-1); // should have been caught during format parsing
}
break;
default: break;
}
return(0);
}

Wyświetl plik

@ -5,8 +5,7 @@
#include <stlink.h>
static void usage(void)
{
static void usage(void) {
puts("st-info --version");
puts("st-info --probe");
puts("st-info --serial");
@ -19,50 +18,43 @@ 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]);
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)
return;
if (!sl) { return; }
printf(" serial: ");
stlink_print_serial(sl, false);
printf(" hla-serial: ");
stlink_print_serial(sl, true);
printf(" flash: %u (pagesize: %u)\n",
(unsigned int)sl->flash_size, (unsigned int)sl->flash_pgsz);
printf(" sram: %u\n", (unsigned int)sl->sram_size);
(uint32_t)sl->flash_size, (uint32_t)sl->flash_pgsz);
printf(" sram: %u\n", (uint32_t)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 +62,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 +78,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)
printf("0x%x\n", (unsigned int)sl->flash_size);
else if (strcmp(av[1], "--pagesize") == 0)
printf("0x%x\n", (unsigned int)sl->flash_pgsz);
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], "--flash") == 0) {
printf("0x%x\n", (uint32_t)sl->flash_size);
} else if (strcmp(av[1], "--pagesize") == 0) {
printf("0x%x\n", (uint32_t)sl->flash_pgsz);
} else if (strcmp(av[1], "--sram") == 0) {
printf("0x%x\n", (uint32_t)sl->sram_size);
} 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);
}

Wyświetl plik

@ -1,7 +1,6 @@
/*
* Copyright (C) 2011 Peter Zotov <whitequark@whitequark.org>
* 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 <whitequark@whitequark.org>
* Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
*/
#include <stdio.h>
@ -9,8 +8,8 @@
#include <stdlib.h>
#include <stdint.h>
#if defined(__MINGW32__) || defined(_MSC_VER)
#include <mingw.h>
#if defined(_WIN32)
#include <win32_socket.h>
#else
#include <unistd.h>
#include <sys/poll.h>
@ -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 @@ start:
*/
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 @@ start:
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 @@ start:
}
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);
}

Wyświetl plik

@ -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_

Plik diff jest za duży Load Diff

Wyświetl plik

@ -8,4 +8,4 @@
#define DEBUG_LOGGING_LEVEL 100
#define DEFAULT_GDB_LISTEN_PORT 4242
#endif
#endif // _GDB_SERVER_H

Wyświetl plik

@ -9,120 +9,87 @@
#include <logging.h>
#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);
}

Wyświetl plik

@ -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_

Wyświetl plik

@ -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_DATAROOTDIR}/${PROJECT_NAME}")
target_link_libraries(stlink-gui ${STLINK_LIB_SHARED} ${SSP_LIB} ${GTK3_LDFLAGS})
install(TARGETS stlink-gui DESTINATION ${CMAKE_INSTALL_BINDIR})
endif ()
endif ()

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,19 +1,18 @@
#ifndef __STLINK_GUI_H__
#define __STLINK_GUI_H__
#include <glib-object.h>
#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__

Wyświetl plik

@ -0,0 +1,638 @@
#include <stlink.h>
#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);
}

Wyświetl plik

@ -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_

Wyświetl plik

@ -33,4 +33,4 @@ enum stlink_debug_commands {
STLINK_DEBUG_ENTER_SWD = 0xa3
};
#endif /* STLINK_COMMANDS_H_ */
#endif // STLINK_COMMANDS_H_

Wyświetl plik

@ -0,0 +1,386 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stlink.h>
#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 30
// wait until done (reaches breakpoint)
for (i = 0; i < WAIT_ROUNDS; i++) {
usleep(10000);
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);
}

Wyświetl plik

@ -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_

Wyświetl plik

@ -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

Wyświetl plik

@ -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 <stddef.h>
#include <stdio.h>
@ -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,27 @@ 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) {
#ifdef __FreeBSD__
// FreeBSD includes its own reimplementation of libusb.
// Its libusb_set_debug() function expects a lib_debug_level
// instead of a lib_log_level and is verbose enough to drown out
// all other output.
switch (v) {
case UDEBUG: return 4;
case UINFO: return 3;
case UWARN: return 2;
case UERROR: return 1;
};
return 2;
case UDEBUG: return (3); // LIBUSB_DEBUG_FUNCTION + LIBUSB_DEBUG_TRANSFER
case UINFO: return (1); // LIBUSB_DEBUG_FUNCTION only
case UWARN: return (0); // LIBUSB_DEBUG_NO
case UERROR: return (0); // LIBUSB_DEBUG_NO
}
return (0);
#else
switch (v) {
case UDEBUG: return (4);
case UINFO: return (3);
case UWARN: return (2);
case UERROR: return (1);
}
return (2);
#endif
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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 <memory.h>
#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 );
}

Wyświetl plik

@ -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 <stdint.h>
#include <stdio.h>
/* 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] */);

Wyświetl plik

@ -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_

Wyświetl plik

@ -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 <stlink.h>
#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);
}

Wyświetl plik

@ -0,0 +1,67 @@
/*
* File: sg.h
* Author: karl
*/
#ifndef STLINK_SG_H
#define STLINK_SG_H
#include <stlink.h>
#include <libusb_settings.h>
#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

Wyświetl plik

@ -0,0 +1,77 @@
/*
* File: usb.h
* Author: karl
*/
#ifndef STLINK_USB_H
#define STLINK_USB_H
#include <stdbool.h>
#include <stlink.h>
#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

Wyświetl plik

@ -1,321 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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;
// 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 <path> <addr> <size>");
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 <path> <addr>");
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 <path>");
o->filename = av[0];
}
else {
return -1; // should have been caught during format parsing
}
break;
default: break ;
}
return 0;
}

Wyświetl plik

@ -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 <stdbool.h>
#include <stlink.h>
#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 */

Wyświetl plik

@ -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.
For license terms, see LICENSE.txt.

Wyświetl plik

@ -0,0 +1,201 @@
#include <stddef.h>
#include <string.h>
#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);
}

Wyświetl plik

@ -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)
}

Wyświetl plik

@ -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;
}

29
src/win32/mmap.h 100644
Wyświetl plik

@ -0,0 +1,29 @@
#ifndef STLINK_MMAP_H
#define STLINK_MMAP_H
#ifdef STLINK_HAVE_SYS_MMAN_H
#include <sys/mman.h>
#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 */

Wyświetl plik

@ -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 <stdlib.h>
#include <stdio.h>
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4820)
#endif
#include <io.h>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#include <getopt.h> // getopt at: https://gist.github.com/ashelly/7776712
#include <process.h> // for getpid() and the exec..() family
#include <direct.h> // 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 <sys/types.h> */
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 <sys/types.h>
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

Wyświetl plik

@ -0,0 +1,316 @@
#if defined(_WIN32)
#include "win32_socket.h"
#undef socket
#undef connect
#undef accept
#undef shutdown
#include <string.h>
#include <errno.h>
#include <assert.h>
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)

Wyświetl plik

@ -1,4 +1,4 @@
#if defined(__MINGW32__) || defined(_MSC_VER)
#if defined(_WIN32)
#define _USE_W32_SOCKETS 1
@ -9,19 +9,20 @@
#include <io.h>
#include <winsock2.h>
#if defined(_MSC_VER)
#pragma comment(lib, "ws2_32.lib")
#endif
#include <unistd.h>
#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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -6,7 +6,7 @@
#include <flash.h>
#if defined(_MSC_VER)
#include <malloc.h>
#include <malloc.h>
#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);
}

Wyświetl plik

@ -1,9 +1,3 @@
/*
* File: test_main.c
*
* main() ripped out of old stlink-hw.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -11,7 +5,7 @@
#include <stlink.h>
#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);
}

Wyświetl plik

@ -3,14 +3,12 @@
#include <stlink.h>
#include <string.h>
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, &regs);
for (off = 0; off < 21; off += 1) stlink_read_reg(sl, off, &regs);
stlink_read_all_regs(sl, &regs);
@ -115,5 +118,6 @@ int main(int ac, char** av) {
stlink_close(sl);
}
return 0;
return(0);
}