From 194e6e9c6b9f3f1c40bf5c6b724aff8087fb443e Mon Sep 17 00:00:00 2001 From: nightwalker-87 <15526941+Nightwalker-87@users.noreply.github.com> Date: Wed, 28 Dec 2022 22:21:47 +0100 Subject: [PATCH] General project clean-up - Removed orphaned old dev-documentation - Rearranged src files belonging to stlink-lib - Revised & sorted option byte source code - Updated devices_boards.md --- CMakeLists.txt | 18 +- doc/dev/app-example/CMakeLists.txt | 22 - doc/dev/app-example/README.md | 2 - doc/dev/app-example/main.c | 28 - doc/dev/developer.txt | 411 -------- doc/dev/pkg-config/CMakeLists.txt | 15 - doc/dev/pkg-config/pkgconfig.pc.cmake | 11 - doc/devices_boards.md | 7 +- inc/stlink.h | 17 - src/st-flash/flash.c | 1 + src/st-util/gdb-server.c | 1 + src/{ => stlink-lib}/calculate.c | 0 src/{ => stlink-lib}/calculate.h | 0 src/{ => stlink-lib}/common.c | 0 src/{ => stlink-lib}/common.h | 0 src/{ => stlink-lib}/common_flash.c | 1 + src/{ => stlink-lib}/common_flash.h | 0 src/stlink-lib/flash_loader.h | 5 +- src/{ => stlink-lib}/flashloader.c | 1 + src/stlink-lib/flashloader.h | 13 + src/{ => stlink-lib}/map_file.c | 0 src/{ => stlink-lib}/map_file.h | 0 src/{ => stlink-lib}/option_bytes.c | 1276 ++++++++++++------------- src/stlink-lib/option_bytes.h | 21 + src/{ => stlink-lib}/read_write.c | 0 25 files changed, 677 insertions(+), 1173 deletions(-) delete mode 100644 doc/dev/app-example/CMakeLists.txt delete mode 100644 doc/dev/app-example/README.md delete mode 100644 doc/dev/app-example/main.c delete mode 100644 doc/dev/developer.txt delete mode 100644 doc/dev/pkg-config/CMakeLists.txt delete mode 100644 doc/dev/pkg-config/pkgconfig.pc.cmake rename src/{ => stlink-lib}/calculate.c (100%) rename src/{ => stlink-lib}/calculate.h (100%) rename src/{ => stlink-lib}/common.c (100%) rename src/{ => stlink-lib}/common.h (100%) rename src/{ => stlink-lib}/common_flash.c (99%) rename src/{ => stlink-lib}/common_flash.h (100%) rename src/{ => stlink-lib}/flashloader.c (99%) create mode 100644 src/stlink-lib/flashloader.h rename src/{ => stlink-lib}/map_file.c (100%) rename src/{ => stlink-lib}/map_file.h (100%) rename src/{ => stlink-lib}/option_bytes.c (73%) create mode 100644 src/stlink-lib/option_bytes.h rename src/{ => stlink-lib}/read_write.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 124f12f..3a22fde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,8 +170,8 @@ add_subdirectory(inc) set(STLINK_HEADERS inc/backend.h inc/stlink.h - src/common_flash.h - src/calculate.h + src/stlink-lib/common_flash.h + src/stlink-lib/calculate.h src/stlink-lib/commands.h src/stlink-lib/libusb_settings.h src/stlink-lib/reg.h @@ -185,13 +185,13 @@ set(STLINK_HEADERS ) set(STLINK_SOURCE - src/read_write.c - src/common.c - src/option_bytes.c - src/common_flash.c - src/map_file.c - src/flashloader.c - src/calculate.c + src/stlink-lib/read_write.c + src/stlink-lib/common.c + src/stlink-lib/option_bytes.c + src/stlink-lib/common_flash.c + src/stlink-lib/map_file.c + src/stlink-lib/flashloader.c + src/stlink-lib/calculate.c src/stlink-lib/chipid.c src/stlink-lib/flash_loader.c src/stlink-lib/logging.c diff --git a/doc/dev/app-example/CMakeLists.txt b/doc/dev/app-example/CMakeLists.txt deleted file mode 100644 index 69ba209..0000000 --- a/doc/dev/app-example/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Warning: This example assumes that you are building on a host with pkg-config available (e.g. linux). -# The logic required to build under windows/mingw was intentionally omitted to keep this CMakeLists as small as possible. - -cmake_minimum_required(VERSION 3.4.2) - -project(st-hello) -set(PROJECT_VERSION 0.1) - -set(SRCS main.c) - -include_directories(${STLINK_INCLUDE_DIRS}) - -find_package(PkgConfig) -pkg_check_modules(STLINK REQUIRED stlink) - -set(CMAKE_C_FLAGS " ${STLINK_CFLAGS_OTHER} -Wall -Werror") - -add_executable(${PROJECT_NAME} ${SRCS}) - -target_link_libraries(${PROJECT_NAME} ${STLINK_LIBRARIES}) - -install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/doc/dev/app-example/README.md b/doc/dev/app-example/README.md deleted file mode 100644 index f3a0bf9..0000000 --- a/doc/dev/app-example/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This is a simple standalone application example that uses libstlink. -It can be used as a boilerplate for app development. diff --git a/doc/dev/app-example/main.c b/doc/dev/app-example/main.c deleted file mode 100644 index b8e64b2..0000000 --- a/doc/dev/app-example/main.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include - -static stlink_t *stlink_open_first(void) { - stlink_t* sl = NULL; - sl = stlink_v1_open(0, 1); - if (sl == NULL) - sl = stlink_open_usb(0, 1, NULL); - - return sl; -} - - -int main() { - stlink_t* sl = NULL; - sl = stlink_open_first(); - - if (sl == NULL) { - fprintf(stderr, "Failed to open stlink device ;(\n"); - exit(1); - } - - fprintf(stderr, "STlink device opened, that's cool!\n"); - stlink_close(sl); - - return 0; -} diff --git a/doc/dev/developer.txt b/doc/dev/developer.txt deleted file mode 100644 index e3091c0..0000000 --- a/doc/dev/developer.txt +++ /dev/null @@ -1,411 +0,0 @@ -=== 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: -- chip id: 0xE0042000 or 0x40015800, primary information to derive flash and sram architection -- core id: Result from the STLINK_DEBUGREADCOREID call, additionally used for flash/sram architection -- cpu id: 0xE000ED00 (CMSIS System Control Block CPU ID), not used in stlink - - -=== Backend === - -The "backend" implements the interface to the adapter hardware. -There are two backends for two different adapters: "sg" (stlink v1?) and "usb" (stlink v2?). - - - -Include stlink/backend.h - typedef struct _stlink_backend { - void (*close) (stlink_t * sl); - int (*exit_debug_mode) (stlink_t * sl); - int (*enter_swd_mode) (stlink_t * sl); - int (*enter_jtag_mode) (stlink_t * stl); - int (*exit_dfu_mode) (stlink_t * stl); - int (*core_id) (stlink_t * stl); - int (*reset) (stlink_t * stl); - int (*jtag_reset) (stlink_t * stl, int value); - int (*run) (stlink_t * stl); - int (*status) (stlink_t * stl); - int (*version) (stlink_t *sl); - int (*read_debug32) (stlink_t *sl, uint32_t addr, uint32_t *data); - int (*read_mem32) (stlink_t *sl, uint32_t addr, uint16_t len); - int (*write_debug32) (stlink_t *sl, uint32_t addr, uint32_t data); - int (*write_mem32) (stlink_t *sl, uint32_t addr, uint16_t len); - int (*write_mem8) (stlink_t *sl, uint32_t addr, uint16_t len); - int (*read_all_regs) (stlink_t *sl, struct stlink_reg * regp); - int (*read_reg) (stlink_t *sl, int r_idx, struct stlink_reg * regp); - int (*read_all_unsupported_regs) (stlink_t *sl, struct stlink_reg *regp); - int (*read_unsupported_reg) (stlink_t *sl, int r_idx, struct stlink_reg *regp); - int (*write_unsupported_reg) (stlink_t *sl, uint32_t value, int idx, struct stlink_reg *regp); - int (*write_reg) (stlink_t *sl, uint32_t reg, int idx); - int (*step) (stlink_t * stl); - 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); - } stlink_backend_t; - -Descriptions below describe the actions of the usb.h backend: - -void (*close) (stlink_t * sl); -int (*exit_debug_mode) (stlink_t * sl); - __stlink_usb_exit_debug_mode: Send STLINK_DEBUG_EXIT - returns -1 or 0 - -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); - _stlink_usb_exit_dfu_mode: Send STLINK_DFU_EXIT - returns -1 or 0 - -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 - 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 - -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". - returns -1 or 0 - -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 - 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" - returns -1 or 0 - -int (*write_mem32) (stlink_t *sl, uint32_t addr, uint16_t len); - _stlink_usb_write_mem32: Use STLINK_DEBUG_WRITEMEM_32BIT to - send data stored in sl->q_buf to the target at "addr". - "len" is the size data (???? not clear whether this are bytes ) - returns -1 or 0 - -int (*write_mem8) (stlink_t *sl, uint32_t addr, uint16_t len); - _stlink_usb_write_mem8: Use STLINK_DEBUG_WRITEMEM_8BIT to - send data stored in sl->q_buf to the target at "addr". - "len" is the size in bytes (probably). - returns -1 or 0 - -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. - 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. - returns -1 or 0 - -int (*read_unsupported_reg) (stlink_t *sl, int r_idx, struct stlink_reg *regp); - _stlink_usb_read_unsupported_reg Use DCRSR and DCRDR to access some - of the internal registers (primask, basepri, faultmask, control, fpscr). - 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: - primask (idx=0x1c), basepri (idx=0x1d), faultmask (idx=0x1e), control (idx=0x1f) - The new value is given as "value" as fn argument. - Corresponding values are refreshed in regp, however the old value for is kept in regp: - If basepri has to be updated (idx=0x1d), then all register values are fetched and - basepri is updated in the core, but not in *regp (BUG???). - 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" - 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. - returns -1 or the value for the current mode. - Modes probably are: - STLINK_DEV_DFU_MODE 0x00 - STLINK_DEV_MASS_MODE 0x01 - STLINK_DEV_DEBUG_MODE 0x02 - -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); - _stlink_usb_set_swdclk: Send STLINK_DEBUG_APIV2_SWD_SET_FREQ and "divisor" value - returns -1 or 0 - - -=== Other Functions === - - -Include: stlink.h - - -Prototype: void stlink_close(stlink_t *sl); -Include: inc/stlink.h -Definition: src/common.c -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: - 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 - Usage includes the selection of the correct flash algorithm. -Backend: "core_id" -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_reset(stlink_t *sl); -Definition: src/common.c -Description: - Just calls the backend "reset" procedure (reset via STLINK_DEBUG_RESETSYS - and reset via AIRCR register at 0xE000ED0C) -Backend: "reset" -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_jtag_reset(stlink_t *sl, int value); -Definition: src/common.c -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: pulse -Return: -1 for error. 0 for success. - - -Include: inc/stlink.h -Prototype: int stlink_run(stlink_t *sl, enum run_type type); -Definition: src/common.c -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() - type: RUN_NORMAL - run target, RUN_FLASH_LOADER - run target with masking interrupts -Return: -1 for error. 0 for success. - -Include: inc/stlink.h -Prototype: int stlink_status(stlink_t *sl); -Definition: src/common.c -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 - STLINK_CORE_HALTED - STLINK_CORE_STAT_UNKNOWN -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: - 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" -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_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); - int stlink_read_all_regs(stlink_t *sl, struct stlink_reg *regp); - int stlink_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp); - int stlink_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp); - int stlink_read_unsupported_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp); - int stlink_write_unsupported_reg(stlink_t *sl, uint32_t value, int r_idx, struct stlink_reg *regp); - int stlink_write_reg(stlink_t *sl, uint32_t reg, int idx); - int stlink_step(stlink_t *sl); - int stlink_current_mode(stlink_t *sl); - int stlink_force_debug(stlink_t *sl); - int stlink_target_voltage(stlink_t *sl); - int stlink_set_swdclk(stlink_t *sl, int freq_khz); - - int stlink_erase_flash_mass(stlink_t* sl); - int stlink_write_flash(stlink_t* sl, stm32_addr_t address, uint8_t* data, uint32_t length, uint8_t eraseonly); - int stlink_parse_ihex(const char* path, uint8_t erased_pattern, uint8_t * * mem, size_t * size, uint32_t * begin); - uint8_t stlink_get_erased_pattern(stlink_t *sl); - int stlink_mwrite_flash(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr_t addr); - int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr); - int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr); - int stlink_fwrite_option_bytes_32bit(stlink_t *sl,uint32_t val); - int stlink_mwrite_sram(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr_t addr); - int stlink_fwrite_sram(stlink_t *sl, const char* path, stm32_addr_t addr); - int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, uint32_t length); - -Include: inc/stlink.h -Prototype: int stlink_chip_id(stlink_t *sl, uint32_t *chip_id); -Definition: src/common.c -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(): - Do not call this function, but instead call stlink_load_device_params() -Backend: - -Arguments: - sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb() - chip_id: Pointer. Result is stored via this pointer. -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: - 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 - cpuid->variant - cpuid->part - cpuid->revision - The result is not used in the tools, but only in the usb test program. -Backend: - -Arguments: - sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb() - 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: - 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: - -Arguments: - sl: Pointer to the stlink data structure, returned by stlink_v1_open() or stlink_open_usb() -Return: - - - - unsigned int is_bigendian(void); - uint32_t read_uint32(const unsigned char *c, const int pt); - void write_uint32(unsigned char* buf, uint32_t ui); - void write_uint16(unsigned char* buf, uint16_t ui); - bool stlink_is_core_halted(stlink_t *sl); - 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: - 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 -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); - - -Include "flash_loader.h" - -int stlink_flash_loader_init(stlink_t *sl, flash_loader_t* fl); -int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size); -int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size); - - -Inlcude "sg.h" -stlink_t* stlink_v1_open(const int verbose, int reset); - -Include "usb.h" - -stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[STLINK_SERIAL_MAX_SIZE]); -size_t stlink_probe_usb(stlink_t **stdevs[]); -void stlink_probe_usb_free(stlink_t **stdevs[], size_t size); diff --git a/doc/dev/pkg-config/CMakeLists.txt b/doc/dev/pkg-config/CMakeLists.txt deleted file mode 100644 index 53870fe..0000000 --- a/doc/dev/pkg-config/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -set(PKG_CONFIG_LIBDIR "\${prefix}/lib/\${deb_host_multiarch}") -set(PKG_CONFIG_INCLUDEDIR "\${prefix}/include/\${deb_host_multiarch}/${PROJECT_NAME}") -set(PKG_CONFIG_LIBS "-L\${libdir} -l:libstlink.so.${PROJECT_VERSION_MAJOR}") -set(PKG_CONFIG_CFLAGS "-I\${includedir}") -set(PKG_CONFIG_REQUIRES "libusb-1.0") - -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig.pc.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" - ) - -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" - DESTINATION ${STLINK_LIBRARY_PATH}/pkgconfig - ) diff --git a/doc/dev/pkg-config/pkgconfig.pc.cmake b/doc/dev/pkg-config/pkgconfig.pc.cmake deleted file mode 100644 index 4f881da..0000000 --- a/doc/dev/pkg-config/pkgconfig.pc.cmake +++ /dev/null @@ -1,11 +0,0 @@ -prefix=${CMAKE_INSTALL_PREFIX} -deb_host_multiarch=${CMAKE_LIBRARY_PATH} -libdir=${PKG_CONFIG_LIBDIR} -includedir=${PKG_CONFIG_INCLUDEDIR} - -Name: ${PROJECT_NAME} -Description: ${PROJECT_DESCRIPTION} -Version: ${PROJECT_VERSION} -Libs: ${PKG_CONFIG_LIBS} -Cflags: ${PKG_CONFIG_CFLAGS} -Requires: ${PKG_CONFIG_REQUIRES} diff --git a/doc/devices_boards.md b/doc/devices_boards.md index 1a5099b..feab9ff 100644 --- a/doc/devices_boards.md +++ b/doc/devices_boards.md @@ -53,10 +53,9 @@ Tested non-official ST boards [incl. STLINK programmers]: ## STM32F1 Clone / ARM Cortex M3 (Core-ID: 0x2ba01477) [may work, but without support!] -| Product-Code | Chip-ID | STLink
Programmer | Boards | -| ------------- | ------- | ---------------------- | ----------------------------------------------------------------------------------------------- | -| CKS32F103C8Tx | 0x410 | v2 | "STM32"-Bluepill ( _**Fake-Marking !**_ )
STM32F103C8T6 clone from China Key Systems (CKS) | -| CKS32F103C8Tx | 0x410 | v2 | CKS32-Bluepill (Clone)
STM32F103C8T6 clone from China Key Systems (CKS) | +| Product-Code | Chip-ID | STLink
Programmer | Boards | +| ------------- | ------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| CKS32F103C8Tx | 0x410 | v2 | STM32F103C8T6 clone from China Key Systems (CKS) either as
CKS32-Bluepill or even as "STM32"-Bluepill with _**Fake-Marking !**_ | ## STM32F3 / ARM Cortex M4F diff --git a/inc/stlink.h b/inc/stlink.h index 17601fd..b9379e0 100644 --- a/inc/stlink.h +++ b/inc/stlink.h @@ -296,23 +296,6 @@ 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); int stlink_load_device_params(stlink_t *sl); -int stlink_read_option_bytes32(stlink_t *sl, uint32_t* option_byte); -int stlink_read_option_bytes_boot_add32(stlink_t *sl, uint32_t* option_byte); -int stlink_read_option_control_register32(stlink_t *sl, uint32_t* option_byte); -int stlink_read_option_control_register1_32(stlink_t *sl, uint32_t* option_byte); - -int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte); -int stlink_write_option_bytes_boot_add32(stlink_t *sl, uint32_t option_bytes_boot_add); -int stlink_write_option_control_register32(stlink_t *sl, uint32_t option_control_register); -int stlink_write_option_control_register1_32(stlink_t *sl, uint32_t option_control_register1); - -int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len); -int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr); - -int stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl); -int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t addr, uint8_t* base, uint32_t len); -int stlink_flashloader_stop(stlink_t *sl, flash_loader_t *fl); - int stlink_target_connect(stlink_t *sl, enum connect_type connect); #include diff --git a/src/st-flash/flash.c b/src/st-flash/flash.c index 058501a..0985c75 100644 --- a/src/st-flash/flash.c +++ b/src/st-flash/flash.c @@ -11,6 +11,7 @@ #include #include #include "flash.h" +#include "option_bytes.h" static stlink_t *connected_stlink = NULL; diff --git a/src/st-util/gdb-server.c b/src/st-util/gdb-server.c index cef79dd..802e23c 100644 --- a/src/st-util/gdb-server.c +++ b/src/st-util/gdb-server.c @@ -28,6 +28,7 @@ #include #include #include +#include "flashloader.h" #include "gdb-remote.h" #include "gdb-server.h" #include "semihosting.h" diff --git a/src/calculate.c b/src/stlink-lib/calculate.c similarity index 100% rename from src/calculate.c rename to src/stlink-lib/calculate.c diff --git a/src/calculate.h b/src/stlink-lib/calculate.h similarity index 100% rename from src/calculate.h rename to src/stlink-lib/calculate.h diff --git a/src/common.c b/src/stlink-lib/common.c similarity index 100% rename from src/common.c rename to src/stlink-lib/common.c diff --git a/src/common.h b/src/stlink-lib/common.h similarity index 100% rename from src/common.h rename to src/stlink-lib/common.h diff --git a/src/common_flash.c b/src/stlink-lib/common_flash.c similarity index 99% rename from src/common_flash.c rename to src/stlink-lib/common_flash.c index 1735297..b21929d 100644 --- a/src/common_flash.c +++ b/src/stlink-lib/common_flash.c @@ -3,6 +3,7 @@ #include #include #include "calculate.h" +#include "flashloader.h" #include "common_flash.h" #include "map_file.h" #include "common.h" diff --git a/src/common_flash.h b/src/stlink-lib/common_flash.h similarity index 100% rename from src/common_flash.h rename to src/stlink-lib/common_flash.h diff --git a/src/stlink-lib/flash_loader.h b/src/stlink-lib/flash_loader.h index 85b92be..368b6ab 100644 --- a/src/stlink-lib/flash_loader.h +++ b/src/stlink-lib/flash_loader.h @@ -1,8 +1,7 @@ /* - * File: stlink.h + * File: flash_loader.h * - * This should contain all the common top level stlink interfaces, - * regardless of how the backend does the work.... + * Flash loader */ #ifndef STLINK_FLASH_LOADER_H_ diff --git a/src/flashloader.c b/src/stlink-lib/flashloader.c similarity index 99% rename from src/flashloader.c rename to src/stlink-lib/flashloader.c index b9c26bf..abb140f 100644 --- a/src/flashloader.c +++ b/src/stlink-lib/flashloader.c @@ -1,6 +1,7 @@ #include #include #include +#include "flashloader.h" #include "common_flash.h" #define L1_WRITE_BLOCK_SIZE 0x80 diff --git a/src/stlink-lib/flashloader.h b/src/stlink-lib/flashloader.h new file mode 100644 index 0000000..ff16d18 --- /dev/null +++ b/src/stlink-lib/flashloader.h @@ -0,0 +1,13 @@ +/* + * File: flashloader.h + * + * Flash loader + */ + +#include +#include + +int stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl); +int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t addr, uint8_t* base, uint32_t len); +int stlink_flashloader_stop(stlink_t *sl, flash_loader_t *fl); + diff --git a/src/map_file.c b/src/stlink-lib/map_file.c similarity index 100% rename from src/map_file.c rename to src/stlink-lib/map_file.c diff --git a/src/map_file.h b/src/stlink-lib/map_file.h similarity index 100% rename from src/map_file.h rename to src/stlink-lib/map_file.h diff --git a/src/option_bytes.c b/src/stlink-lib/option_bytes.c similarity index 73% rename from src/option_bytes.c rename to src/stlink-lib/option_bytes.c index c1a4182..44cd393 100644 --- a/src/option_bytes.c +++ b/src/stlink-lib/option_bytes.c @@ -1,152 +1,32 @@ #include #include #include +#include "option_bytes.h" #include "common_flash.h" #include "map_file.h" #include "common.h" + /** - * Read option bytes + * Read option control register F0 * @param sl - * @param option_byte value to write + * @param option_byte * @return 0 on success, -ve on failure. */ -int stlink_read_option_control_register_Gx(stlink_t *sl, - uint32_t *option_byte) { - return stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, option_byte); +int stlink_read_option_control_register_f0(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option control register byte from %#10x\n", FLASH_OBR); + return stlink_read_debug32(sl, FLASH_OBR, option_byte); } /** - * Read option bytes + * Write option bytes F0 * @param sl - * @param option_byte value to write - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_bytes_Gx(stlink_t *sl, uint32_t *option_byte) { - return stlink_read_option_control_register_Gx(sl, option_byte); -} - -/** - * Read first option bytes - * @param sl - * @param option_byte option value - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t *option_byte) { - DLOG("@@@@ Read option bytes boot address from %#10x\n", sl->option_base); - return stlink_read_debug32(sl, sl->option_base, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to write - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register_f2(stlink_t *sl, - uint32_t *option_byte) { - return stlink_read_debug32(sl, FLASH_F2_OPT_CR, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to write - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t *option_byte) { - return stlink_read_option_control_register_f2(sl, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register_f4(stlink_t *sl, - uint32_t *option_byte) { - return stlink_read_debug32(sl, FLASH_F4_OPTCR, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t *option_byte) { - return stlink_read_option_control_register_f4(sl, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - * - * Since multiple bytes can be read, we read and print all but one here - * and then return the last one just like other devices - */ -int stlink_read_option_bytes_f7(stlink_t *sl, uint32_t *option_byte) { - int err = -1; - for (uint32_t counter = 0; counter < (sl->option_size / 4 - 1); counter++) { - err = stlink_read_debug32(sl, sl->option_base + counter * sizeof(uint32_t), - option_byte); - if (err == -1) { - return err; - } else { - printf("%08x\n", *option_byte); - } - } - - return stlink_read_debug32( - sl, - sl->option_base + (uint32_t)(sl->option_size / 4 - 1) * sizeof(uint32_t), - option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte option value - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_bytes32(stlink_t *sl, uint32_t *option_byte) { - if (sl->option_base == 0) { - ELOG("Option bytes read is currently not supported for connected chip\n"); - return (-1); - } - - switch (sl->chip_id) { - case STM32_CHIPID_F2: - return stlink_read_option_bytes_f2(sl, option_byte); - case STM32_CHIPID_F4: - case STM32_CHIPID_F446: - return stlink_read_option_bytes_f4(sl, option_byte); - case STM32_CHIPID_F76xxx: - return stlink_read_option_bytes_f7(sl, option_byte); - case STM32_CHIPID_G0_CAT1: - case STM32_CHIPID_G0_CAT2: - case STM32_CHIPID_G4_CAT2: - case STM32_CHIPID_G4_CAT3: - return stlink_read_option_bytes_Gx(sl, option_byte); - default: - return stlink_read_option_bytes_generic(sl, option_byte); - } -} - - -/** - * Write option bytes - * @param sl - * @param base option bytes to write * @param addr of the memory mapped option bytes - * @param len of options bytes to write + * @param base option bytes + * @param len of option bytes * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_f0( - stlink_t *sl, uint8_t* base, stm32_addr_t addr, uint32_t len) { +static int stlink_write_option_bytes_f0(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len) { int ret = 0; if (len < 12 || addr != STM32_F0_OPTION_BYTES_BASE) { @@ -196,133 +76,139 @@ static int stlink_write_option_bytes_f0( } /** - * Write option bytes + * Write option control register F0 * @param sl - * @param addr of the memory mapped option bytes - * @param base option bytes to write + * @param option_cr * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_gx(stlink_t *sl, uint8_t *base, - stm32_addr_t addr, uint32_t len) { - /* Write options bytes */ - uint32_t val; +static int stlink_write_option_control_register_f0(stlink_t *sl, uint32_t option_cr) { int ret = 0; - (void)len; - uint32_t data; + uint16_t opt_val[8]; + unsigned protection, optiondata; + uint16_t user_options, user_data, rdp; + unsigned option_offset, user_data_offset; + ILOG("Asked to write option control register %#10x to %#010x.\n", option_cr, FLASH_OBR); + + /* Clear errors */ clear_flash_error(sl); - write_uint32((unsigned char *)&data, *(uint32_t *)(base)); - WLOG("Writing option bytes %#10x to %#10x\n", data, addr); - stlink_write_debug32(sl, STM32Gx_FLASH_OPTR, data); - - // Set Options Start bit - stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); - val |= (1 << STM32Gx_FLASH_CR_OPTSTRT); - stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); - - wait_flash_busy(sl); - - ret = check_flash_error(sl); - - // Reload options - stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); - val |= (1 << STM32Gx_FLASH_CR_OBL_LAUNCH); - stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); - - return (ret); -} - -/** - * Write option bytes - * @param sl - * @param addr of the memory mapped option bytes - * @param base option bytes to write - * @return 0 on success, -ve on failure. - */ -static int stlink_write_option_bytes_l0(stlink_t *sl, uint8_t *base, - stm32_addr_t addr, uint32_t len) { - uint32_t flash_base = get_stm32l0_flash_base(sl); - uint32_t val; - uint32_t data; - int ret = 0; - - // Clear errors - clear_flash_error(sl); - - while (len != 0) { - write_uint32((unsigned char *)&data, - *(uint32_t *)(base)); // write options bytes - - WLOG("Writing option bytes %#10x to %#10x\n", data, addr); - stlink_write_debug32(sl, addr, data); - wait_flash_busy(sl); - - if ((ret = check_flash_error(sl))) { - break; - } - - len -= 4; - addr += 4; - base += 4; + /* Retrieve current values */ + ret = stlink_read_debug32(sl, FLASH_OBR, &optiondata); + if (ret) { + return ret; + } + ret = stlink_read_debug32(sl, FLASH_WRPR, &protection); + if (ret) { + return ret; } - // Reload options - stlink_read_debug32(sl, flash_base + FLASH_PECR_OFF, &val); - val |= (1 << STM32L0_FLASH_OBL_LAUNCH); - stlink_write_debug32(sl, flash_base + FLASH_PECR_OFF, val); + /* Translate OBR value to flash store structure + * F0: RM0091, Option byte description, pp. 75-78 + * F1: PM0075, Option byte description, pp. 19-22 + * F3: RM0316, Option byte description, pp. 85-87 */ + switch(sl->chip_id) + { + case 0x422: /* STM32F30x */ + case 0x432: /* STM32F37x */ + case 0x438: /* STM32F303x6/8 and STM32F328 */ + case 0x446: /* STM32F303xD/E and STM32F398xE */ + case 0x439: /* STM32F302x6/8 */ + case 0x440: /* STM32F05x */ + case 0x444: /* STM32F03x */ + case 0x445: /* STM32F04x */ + case 0x448: /* STM32F07x */ + case 0x442: /* STM32F09x */ + option_offset = 6; + user_data_offset = 16; + rdp = 0x55AA; + break; + default: + option_offset = 0; + user_data_offset = 10; + rdp = 0x5AA5; + break; + } - return (ret); + user_options = (option_cr >> option_offset >> 2) & 0xFFFF; + user_data = (option_cr >> user_data_offset) & 0xFFFF; + +#define VAL_WITH_COMPLEMENT(v) (uint16_t)(((v)&0xFF) | (((~(v))<<8)&0xFF00)) + + opt_val[0] = (option_cr & (1 << 1/*OPT_READOUT*/)) ? 0xFFFF : rdp; + opt_val[1] = VAL_WITH_COMPLEMENT(user_options); + opt_val[2] = VAL_WITH_COMPLEMENT(user_data); + opt_val[3] = VAL_WITH_COMPLEMENT(user_data >> 8); + opt_val[4] = VAL_WITH_COMPLEMENT(protection); + opt_val[5] = VAL_WITH_COMPLEMENT(protection >> 8); + opt_val[6] = VAL_WITH_COMPLEMENT(protection >> 16); + opt_val[7] = VAL_WITH_COMPLEMENT(protection >> 24); + +#undef VAL_WITH_COMPLEMENT + + /* Write bytes and check errors */ + ret = stlink_write_option_bytes_f0(sl, STM32_F0_OPTION_BYTES_BASE, (uint8_t*)opt_val, sizeof(opt_val)); + if (ret) + return ret; + + ret = check_flash_error(sl); + if (!ret) { + ILOG("Wrote option bytes %#010x to %#010x!\n", option_cr, + FLASH_OBR); + } + + return ret; } /** - * Write option bytes + * Read option control register F2 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_control_register_f2(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_debug32(sl, FLASH_F2_OPT_CR, option_byte); +} + +/** + * Read option bytes F2 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_option_control_register_f2(sl, option_byte); +} + +/** + * Read option control register F4 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_control_register_f4(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_debug32(sl, FLASH_F4_OPTCR, option_byte); +} + +/** + * Read option bytes F4 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_option_control_register_f4(sl, option_byte); +} + +/** + * Write option bytes F4 * @param sl * @param addr of the memory mapped option bytes - * @param base option bytes to write + * @param base option bytes + * @param len of option bytes * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_l4(stlink_t *sl, uint8_t *base, - stm32_addr_t addr, uint32_t len) { - - uint32_t val; - int ret = 0; - (void)addr; - (void)len; - - // Clear errors - clear_flash_error(sl); - - // write options bytes - uint32_t data; - write_uint32((unsigned char *)&data, *(uint32_t *)(base)); - WLOG("Writing option bytes 0x%04x\n", data); - stlink_write_debug32(sl, STM32L4_FLASH_OPTR, data); - - // set options start bit - stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); - val |= (1 << STM32L4_FLASH_CR_OPTSTRT); - stlink_write_debug32(sl, STM32L4_FLASH_CR, val); - - wait_flash_busy(sl); - ret = check_flash_error(sl); - - // apply options bytes immediate - stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); - val |= (1 << STM32L4_FLASH_CR_OBL_LAUNCH); - stlink_write_debug32(sl, STM32L4_FLASH_CR, val); - - return (ret); -} - -/** - * Write option bytes - * @param sl - * @param option_byte value to write - * @return 0 on success, -ve on failure. - */ -static int stlink_write_option_bytes_f4(stlink_t *sl, uint8_t *base, - stm32_addr_t addr, uint32_t len) { +static int stlink_write_option_bytes_f4(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { uint32_t option_byte; int ret = 0; (void)addr; @@ -346,13 +232,40 @@ static int stlink_write_option_bytes_f4(stlink_t *sl, uint8_t *base, } /** - * Write option bytes + * Read option bytes F7 * @param sl - * @param option_byte value to write + * @param option_byte * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_f7(stlink_t *sl, uint8_t *base, - stm32_addr_t addr, uint32_t len) { +// Since multiple bytes can be read, we read and print all, but one here +// and then return the last one just like other devices. +int stlink_read_option_bytes_f7(stlink_t *sl, uint32_t *option_byte) { + int err = -1; + for (uint32_t counter = 0; counter < (sl->option_size / 4 - 1); counter++) { + err = stlink_read_debug32(sl, sl->option_base + counter * sizeof(uint32_t), + option_byte); + if (err == -1) { + return err; + } else { + printf("%08x\n", *option_byte); + } + } + + return stlink_read_debug32( + sl, + sl->option_base + (uint32_t)(sl->option_size / 4 - 1) * sizeof(uint32_t), + option_byte); +} + +/** + * Write option bytes F7 + * @param sl + * @param addr of the memory mapped option bytes + * @param base option bytes + * @param len of option bytes + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_bytes_f7(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { uint32_t option_byte; int ret = 0; @@ -402,15 +315,183 @@ static int stlink_write_option_bytes_f7(stlink_t *sl, uint8_t *base, } /** - * Write STM32H7xx option bytes + * Read option control register F7 * @param sl - * @param base option bytes to write - * @param addr of the memory mapped option bytes - * @param len number of bytes to write (must be multiple of 4) + * @param option_byte * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_h7(stlink_t *sl, uint8_t *base, - stm32_addr_t addr, uint32_t len) { +int stlink_read_option_control_register_f7(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option control register byte from %#10x\n", FLASH_F7_OPTCR); + return stlink_read_debug32(sl, FLASH_F7_OPTCR, option_byte); +} + +/** + * Write option control register F7 + * @param sl + * @param option_cr + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_control_register_f7(stlink_t *sl, uint32_t option_cr) { + int ret = 0; + + // Clear errors + clear_flash_error(sl); + + ILOG("Asked to write option control register 1 %#10x to %#010x.\n", + option_cr, FLASH_F7_OPTCR); + + /* write option byte, ensuring we dont lock opt, and set strt bit */ + stlink_write_debug32(sl, FLASH_F7_OPTCR, + (option_cr & ~(1 << FLASH_F7_OPTCR_LOCK)) | + (1 << FLASH_F7_OPTCR_START)); + + wait_flash_busy(sl); + + ret = check_flash_error(sl); + if (!ret) + ILOG("Wrote option bytes %#010x to %#010x!\n", option_cr, + FLASH_F7_OPTCR); + + return ret; +} + +/** + * Read option control register1 F7 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_control_register1_f7(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option control register 1 byte from %#10x\n", + FLASH_F7_OPTCR1); + return stlink_read_debug32(sl, FLASH_F7_OPTCR1, option_byte); +} + +/** + * Write option control register1 F7 + * @param sl + * @param option_cr1 + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_control_register1_f7(stlink_t *sl, uint32_t option_cr1) { + int ret = 0; + + // Clear errors + clear_flash_error(sl); + + ILOG("Asked to write option control register 1 %#010x to %#010x.\n", + option_cr1, FLASH_F7_OPTCR1); + + /* write option byte, ensuring we dont lock opt, and set strt bit */ + uint32_t current_control_register_value; + stlink_read_debug32(sl, FLASH_F7_OPTCR, ¤t_control_register_value); + + /* write option byte */ + stlink_write_debug32(sl, FLASH_F7_OPTCR1, option_cr1); + stlink_write_debug32( + sl, FLASH_F7_OPTCR, + (current_control_register_value & ~(1 << FLASH_F7_OPTCR_LOCK)) | + (1 << FLASH_F7_OPTCR_START)); + + wait_flash_busy(sl); + + ret = check_flash_error(sl); + if (!ret) + ILOG("Wrote option bytes %#010x to %#010x!\n", option_cr1, FLASH_F7_OPTCR1); + + return ret; +} + +/** + * Read option bytes boot address F7 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_bytes_boot_add_f7(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option byte boot address\n"); + return stlink_read_option_control_register1_f7(sl, option_byte); +} + +/** + * Write option bytes boot address F7 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +static int +stlink_write_option_bytes_boot_add_f7(stlink_t *sl, uint32_t option_byte_boot_add) { + ILOG("Asked to write option byte boot add %#010x.\n", option_byte_boot_add); + return stlink_write_option_control_register1_f7(sl, option_byte_boot_add); +} + +/** + * Read option control register Gx + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_control_register_gx(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, option_byte); +} + +/** + * Read option bytes Gx + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_bytes_gx(stlink_t *sl, uint32_t *option_byte) { + return stlink_read_option_control_register_gx(sl, option_byte); +} + +/** + * Write option bytes Gx + * @param sl + * @param addr of the memory mapped option bytes + * @param base option bytes + * @param len of option bytes + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_bytes_gx(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { + /* Write options bytes */ + uint32_t val; + int ret = 0; + (void)len; + uint32_t data; + + clear_flash_error(sl); + + write_uint32((unsigned char *)&data, *(uint32_t *)(base)); + WLOG("Writing option bytes %#10x to %#10x\n", data, addr); + stlink_write_debug32(sl, STM32Gx_FLASH_OPTR, data); + + // Set Options Start bit + stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); + val |= (1 << STM32Gx_FLASH_CR_OPTSTRT); + stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); + + wait_flash_busy(sl); + + ret = check_flash_error(sl); + + // Reload options + stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); + val |= (1 << STM32Gx_FLASH_CR_OBL_LAUNCH); + stlink_write_debug32(sl, STM32Gx_FLASH_CR, val); + + return (ret); +} + +/** + * Write option bytes H7 + * @param sl + * @param addr of the memory mapped option bytes + * @param base option bytes + * @param len of option bytes + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_bytes_h7(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { uint32_t val; uint32_t data; @@ -473,14 +554,96 @@ static int stlink_write_option_bytes_h7(stlink_t *sl, uint8_t *base, } /** - * Write option bytes + * Write option bytes L0 * @param sl * @param addr of the memory mapped option bytes - * @param base option bytes to write + * @param base option bytes + * @param len of option bytes * @return 0 on success, -ve on failure. */ -static int stlink_write_option_bytes_wb(stlink_t *sl, uint8_t *base, - stm32_addr_t addr, uint32_t len) { +static int stlink_write_option_bytes_l0(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { + uint32_t flash_base = get_stm32l0_flash_base(sl); + uint32_t val; + uint32_t data; + int ret = 0; + + // Clear errors + clear_flash_error(sl); + + while (len != 0) { + write_uint32((unsigned char *)&data, + *(uint32_t *)(base)); // write options bytes + + WLOG("Writing option bytes %#10x to %#10x\n", data, addr); + stlink_write_debug32(sl, addr, data); + wait_flash_busy(sl); + + if ((ret = check_flash_error(sl))) { + break; + } + + len -= 4; + addr += 4; + base += 4; + } + + // Reload options + stlink_read_debug32(sl, flash_base + FLASH_PECR_OFF, &val); + val |= (1 << STM32L0_FLASH_OBL_LAUNCH); + stlink_write_debug32(sl, flash_base + FLASH_PECR_OFF, val); + + return (ret); +} + +/** + * Write option bytes L4 + * @param sl + * @param addr of the memory mapped option bytes + * @param base option bytes + * @param len of option bytes + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_bytes_l4(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { + + uint32_t val; + int ret = 0; + (void)addr; + (void)len; + + // Clear errors + clear_flash_error(sl); + + // write options bytes + uint32_t data; + write_uint32((unsigned char *)&data, *(uint32_t *)(base)); + WLOG("Writing option bytes 0x%04x\n", data); + stlink_write_debug32(sl, STM32L4_FLASH_OPTR, data); + + // set options start bit + stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); + val |= (1 << STM32L4_FLASH_CR_OPTSTRT); + stlink_write_debug32(sl, STM32L4_FLASH_CR, val); + + wait_flash_busy(sl); + ret = check_flash_error(sl); + + // apply options bytes immediate + stlink_read_debug32(sl, STM32L4_FLASH_CR, &val); + val |= (1 << STM32L4_FLASH_CR_OBL_LAUNCH); + stlink_write_debug32(sl, STM32L4_FLASH_CR, val); + + return (ret); +} + +/** + * Write option bytes WB + * @param sl + * @param addr of the memory mapped option bytes + * @param base option bytes + * @param len of option bytes + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_bytes_wb(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { /* Write options bytes */ uint32_t val; int ret = 0; @@ -490,8 +653,7 @@ static int stlink_write_option_bytes_wb(stlink_t *sl, uint8_t *base, clear_flash_error(sl); while (len != 0) { - write_uint32((unsigned char *)&data, - *(uint32_t *)(base)); // write options bytes + write_uint32((unsigned char *)&data, *(uint32_t *)(base)); // write options bytes WLOG("Writing option bytes %#10x to %#10x\n", data, addr); stlink_write_debug32(sl, addr, data); @@ -523,15 +685,71 @@ static int stlink_write_option_bytes_wb(stlink_t *sl, uint8_t *base, return (ret); } +/** + * Read option control register WB + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_control_register_wb(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option control register byte from %#10x\n", STM32WB_FLASH_OPTR); + return stlink_read_debug32(sl, STM32WB_FLASH_OPTR, option_byte); +} + +/** + * Write option control register WB + * @param sl + * @param option_cr + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_control_register_wb(stlink_t *sl, uint32_t option_cr) { + int ret = 0; + + // Clear errors + clear_flash_error(sl); + + ILOG("Asked to write option control register 1 %#10x to %#010x.\n", + option_cr, STM32WB_FLASH_OPTR); + + /* write option byte, ensuring we dont lock opt, and set strt bit */ + stlink_write_debug32(sl, STM32WB_FLASH_OPTR, option_cr); + + wait_flash_busy(sl); + + // Set Options Start bit + uint32_t val = (1 << STM32WB_FLASH_CR_OPTSTRT); + stlink_write_debug32(sl, STM32WB_FLASH_CR, val); + + wait_flash_busy(sl); + + ret = check_flash_error(sl); + if (!ret) + ILOG("Wrote option bytes %#010x to %#010x!\n", option_cr, STM32WB_FLASH_OPTR); + + return ret; +} + +/** + * Read option bytes generic + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_bytes_generic(stlink_t *sl, uint32_t *option_byte) { + DLOG("@@@@ Read option bytes boot address from %#10x\n", sl->option_base); + return stlink_read_debug32(sl, sl->option_base, option_byte); +} + + /** * Write option bytes * @param sl * @param addr of the memory mapped option bytes - * @param base option bytes to write + * @param base option bytes + * @param len of option bytes * @return 0 on success, -ve on failure. */ -int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t *base, - uint32_t len) { +int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { int ret = -1; if (sl->option_base == 0) { @@ -566,29 +784,29 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t *base, switch (sl->flash_type) { case STM32_FLASH_TYPE_F0_F1_F3: case STM32_FLASH_TYPE_F1_XL: - ret = stlink_write_option_bytes_f0(sl, base, addr, len); + ret = stlink_write_option_bytes_f0(sl, addr, base, len); break; case STM32_FLASH_TYPE_F2_F4: - ret = stlink_write_option_bytes_f4(sl, base, addr, len); + ret = stlink_write_option_bytes_f4(sl, addr, base, len); break; case STM32_FLASH_TYPE_F7: - ret = stlink_write_option_bytes_f7(sl, base, addr, len); + ret = stlink_write_option_bytes_f7(sl, addr, base, len); break; case STM32_FLASH_TYPE_L0_L1: - ret = stlink_write_option_bytes_l0(sl, base, addr, len); + ret = stlink_write_option_bytes_l0(sl, addr, base, len); break; case STM32_FLASH_TYPE_L4_L4P: - ret = stlink_write_option_bytes_l4(sl, base, addr, len); + ret = stlink_write_option_bytes_l4(sl, addr, base, len); break; case STM32_FLASH_TYPE_G0: case STM32_FLASH_TYPE_G4: - ret = stlink_write_option_bytes_gx(sl, base, addr, len); + ret = stlink_write_option_bytes_gx(sl, addr, base, len); break; case STM32_FLASH_TYPE_H7: - ret = stlink_write_option_bytes_h7(sl, base, addr, len); + ret = stlink_write_option_bytes_h7(sl, addr, base, len); break; case STM32_FLASH_TYPE_WB_WL: - ret = stlink_write_option_bytes_wb(sl, base, addr, len); + ret = stlink_write_option_bytes_wb(sl, addr, base, len); break; default: ELOG("Option bytes writing is currently not implemented for connected " @@ -609,210 +827,66 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t *base, return ret; } - /** - * Write option bytes + * Write the given binary file with option bytes * @param sl - * @param option_byte value to write + * @param path readable file path, should be binary image + * @param addr of the memory mapped option bytes * @return 0 on success, -ve on failure. */ -static int -stlink_write_option_control_register_f0(stlink_t *sl, - uint32_t option_control_register) { - int ret = 0; - uint16_t opt_val[8]; - unsigned protection, optiondata; - uint16_t user_options, user_data, rdp; - unsigned option_offset, user_data_offset; +int stlink_fwrite_option_bytes(stlink_t *sl, const char *path, stm32_addr_t addr) { + /* Write the file in flash at addr */ + int err; + mapped_file_t mf = MAPPED_FILE_INITIALIZER; - ILOG("Asked to write option control register %#10x to %#010x.\n", - option_control_register, FLASH_OBR); - - /* Clear errors */ - clear_flash_error(sl); - - /* Retrieve current values */ - ret = stlink_read_debug32(sl, FLASH_OBR, &optiondata); - if (ret) { - return ret; - } - ret = stlink_read_debug32(sl, FLASH_WRPR, &protection); - if (ret) { - return ret; + if (map_file(&mf, path) == -1) { + ELOG("map_file() == -1\n"); + return (-1); } - /* Translate OBR value to flash store structure - * F0: RM0091, Option byte description, pp. 75-78 - * F1: PM0075, Option byte description, pp. 19-22 - * F3: RM0316, Option byte description, pp. 85-87 */ - switch(sl->chip_id) - { - case 0x422: /* STM32F30x */ - case 0x432: /* STM32F37x */ - case 0x438: /* STM32F303x6/8 and STM32F328 */ - case 0x446: /* STM32F303xD/E and STM32F398xE */ - case 0x439: /* STM32F302x6/8 */ - case 0x440: /* STM32F05x */ - case 0x444: /* STM32F03x */ - case 0x445: /* STM32F04x */ - case 0x448: /* STM32F07x */ - case 0x442: /* STM32F09x */ - option_offset = 6; - user_data_offset = 16; - rdp = 0x55AA; - break; + printf("file %s ", path); + md5_calculate(&mf); + stlink_checksum(&mf); + + err = stlink_write_option_bytes(sl, addr, mf.base, (uint32_t)mf.len); + stlink_fwrite_finalize(sl, addr); + unmap_file(&mf); + + return (err); +} + +/** + * Read option control register 32 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_control_register32(stlink_t *sl, uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes read is currently not supported for connected chip\n"); + return -1; + } + + switch (sl->flash_type) { + case STM32_FLASH_TYPE_F0_F1_F3: + case STM32_FLASH_TYPE_F1_XL: + return stlink_read_option_control_register_f0(sl, option_byte); + case STM32_FLASH_TYPE_F7: + return stlink_read_option_control_register_f7(sl, option_byte); + case STM32_FLASH_TYPE_WB_WL: + return stlink_read_option_control_register_wb(sl, option_byte); default: - option_offset = 0; - user_data_offset = 10; - rdp = 0x5AA5; - break; + return -1; } - - user_options = (option_control_register >> option_offset >> 2) & 0xFFFF; - user_data = (option_control_register >> user_data_offset) & 0xFFFF; - -#define VAL_WITH_COMPLEMENT(v) (uint16_t)(((v)&0xFF) | (((~(v))<<8)&0xFF00)) - - opt_val[0] = (option_control_register & (1 << 1/*OPT_READOUT*/)) ? 0xFFFF : rdp; - opt_val[1] = VAL_WITH_COMPLEMENT(user_options); - opt_val[2] = VAL_WITH_COMPLEMENT(user_data); - opt_val[3] = VAL_WITH_COMPLEMENT(user_data >> 8); - opt_val[4] = VAL_WITH_COMPLEMENT(protection); - opt_val[5] = VAL_WITH_COMPLEMENT(protection >> 8); - opt_val[6] = VAL_WITH_COMPLEMENT(protection >> 16); - opt_val[7] = VAL_WITH_COMPLEMENT(protection >> 24); - -#undef VAL_WITH_COMPLEMENT - - /* Write bytes and check errors */ - ret = stlink_write_option_bytes_f0(sl, (uint8_t*)opt_val, STM32_F0_OPTION_BYTES_BASE, sizeof(opt_val)); - if (ret) - return ret; - - ret = check_flash_error(sl); - if (!ret) { - ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register, - FLASH_OBR); - } - - return ret; -} - - -/** - * Write option bytes - * @param sl - * @param option_byte value to write - * @return 0 on success, -ve on failure. - */ -static int -stlink_write_option_control_register1_f7(stlink_t *sl, - uint32_t option_control_register1) { - int ret = 0; - - // Clear errors - clear_flash_error(sl); - - ILOG("Asked to write option control register 1 %#010x to %#010x.\n", - option_control_register1, FLASH_F7_OPTCR1); - - /* write option byte, ensuring we dont lock opt, and set strt bit */ - uint32_t current_control_register_value; - stlink_read_debug32(sl, FLASH_F7_OPTCR, ¤t_control_register_value); - - /* write option byte */ - stlink_write_debug32(sl, FLASH_F7_OPTCR1, option_control_register1); - stlink_write_debug32( - sl, FLASH_F7_OPTCR, - (current_control_register_value & ~(1 << FLASH_F7_OPTCR_LOCK)) | - (1 << FLASH_F7_OPTCR_START)); - - wait_flash_busy(sl); - - ret = check_flash_error(sl); - if (!ret) - ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register1, - FLASH_F7_OPTCR1); - - return ret; } /** - * Write option bytes + * Write option control register 32 * @param sl - * @param option_byte value to write + * @param option_cr * @return 0 on success, -ve on failure. */ -static int -stlink_write_option_control_register_f7(stlink_t *sl, - uint32_t option_control_register) { - int ret = 0; - - // Clear errors - clear_flash_error(sl); - - ILOG("Asked to write option control register 1 %#10x to %#010x.\n", - option_control_register, FLASH_F7_OPTCR); - - /* write option byte, ensuring we dont lock opt, and set strt bit */ - stlink_write_debug32(sl, FLASH_F7_OPTCR, - (option_control_register & ~(1 << FLASH_F7_OPTCR_LOCK)) | - (1 << FLASH_F7_OPTCR_START)); - - wait_flash_busy(sl); - - ret = check_flash_error(sl); - if (!ret) - ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register, - FLASH_F7_OPTCR); - - return ret; -} - -/** - * Write option bytes - * @param sl - * @param option_byte value to write - * @return 0 on success, -ve on failure. - */ -static int -stlink_write_option_control_register_wb(stlink_t *sl, - uint32_t option_control_register) { - int ret = 0; - - // Clear errors - clear_flash_error(sl); - - ILOG("Asked to write option control register 1 %#10x to %#010x.\n", - option_control_register, STM32WB_FLASH_OPTR); - - /* write option byte, ensuring we dont lock opt, and set strt bit */ - stlink_write_debug32(sl, STM32WB_FLASH_OPTR, option_control_register); - - wait_flash_busy(sl); - - // Set Options Start bit - uint32_t val = (1 << STM32WB_FLASH_CR_OPTSTRT); - stlink_write_debug32(sl, STM32WB_FLASH_CR, val); - - wait_flash_busy(sl); - - ret = check_flash_error(sl); - if (!ret) - ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register, - STM32WB_FLASH_OPTR); - - return ret; -} - -/** - * Write option bytes - * @param sl - * @param option bytes boot address to write - * @return 0 on success, -ve on failure. - */ -int stlink_write_option_control_register32(stlink_t *sl, - uint32_t option_control_register) { +int stlink_write_option_control_register32(stlink_t *sl, uint32_t option_cr) { int ret = -1; wait_flash_busy(sl); @@ -831,14 +905,14 @@ int stlink_write_option_control_register32(stlink_t *sl, switch (sl->flash_type) { case STM32_FLASH_TYPE_F0_F1_F3: case STM32_FLASH_TYPE_F1_XL: - ret = stlink_write_option_control_register_f0(sl, option_control_register); + ret = stlink_write_option_control_register_f0(sl, option_cr); break; case STM32_FLASH_TYPE_F7: - ret = stlink_write_option_control_register_f7(sl, option_control_register); + ret = stlink_write_option_control_register_f7(sl, option_cr); break; case STM32_FLASH_TYPE_WB_WL: ret = - stlink_write_option_control_register_wb(sl, option_control_register); + stlink_write_option_control_register_wb(sl, option_cr); break; default: ELOG("Option control register writing is currently not implemented for " @@ -849,7 +923,7 @@ int stlink_write_option_control_register32(stlink_t *sl, if (ret) ELOG("Flash option write failed!\n"); else - ILOG("Wrote option control register %#010x!\n", option_control_register); + ILOG("Wrote option control register %#010x!\n", option_cr); /* Re-lock flash. */ lock_flash_option(sl); @@ -859,13 +933,33 @@ int stlink_write_option_control_register32(stlink_t *sl, } /** - * Write option bytes + * Read option control register1 32 * @param sl - * @param option bytes boot address to write + * @param option_byte * @return 0 on success, -ve on failure. */ -int stlink_write_option_control_register1_32( - stlink_t *sl, uint32_t option_control_register1) { +int stlink_read_option_control_register1_32(stlink_t *sl, uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes read is currently not supported for connected chip\n"); + return -1; + } + + switch (sl->flash_type) { + case STM32_FLASH_TYPE_F7: + return stlink_read_option_control_register1_f7(sl, option_byte); + default: + return -1; + // return stlink_read_option_control_register1_generic(sl, option_byte); + } +} + +/** + * Write option control register1 32 + * @param sl + * @param option_cr + * @return 0 on success, -ve on failure. + */ +int stlink_write_option_control_register1_32(stlink_t *sl, uint32_t option_cr1) { int ret = -1; wait_flash_busy(sl); @@ -884,7 +978,7 @@ int stlink_write_option_control_register1_32( switch (sl->flash_type) { case STM32_FLASH_TYPE_F7: ret = - stlink_write_option_control_register1_f7(sl, option_control_register1); + stlink_write_option_control_register1_f7(sl, option_cr1); break; default: ELOG("Option control register 1 writing is currently not implemented for " @@ -895,7 +989,7 @@ int stlink_write_option_control_register1_32( if (ret) ELOG("Flash option write failed!\n"); else - ILOG("Wrote option control register 1 %#010x!\n", option_control_register1); + ILOG("Wrote option control register 1 %#010x!\n", option_cr1); lock_flash_option(sl); lock_flash(sl); @@ -903,28 +997,80 @@ int stlink_write_option_control_register1_32( return (ret); } - /** - * Write option bytes + * Read option bytes 32 * @param sl - * @param option_byte value to write + * @param option_byte * @return 0 on success, -ve on failure. */ -static int -stlink_write_option_bytes_boot_add_f7(stlink_t *sl, - uint32_t option_byte_boot_add) { - ILOG("Asked to write option byte boot add %#010x.\n", option_byte_boot_add); - return stlink_write_option_control_register1_f7(sl, option_byte_boot_add); +int stlink_read_option_bytes32(stlink_t *sl, uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes read is currently not supported for connected chip\n"); + return (-1); + } + + switch (sl->chip_id) { + case STM32_CHIPID_F2: + return stlink_read_option_bytes_f2(sl, option_byte); + case STM32_CHIPID_F4: + case STM32_CHIPID_F446: + return stlink_read_option_bytes_f4(sl, option_byte); + case STM32_CHIPID_F76xxx: + return stlink_read_option_bytes_f7(sl, option_byte); + case STM32_CHIPID_G0_CAT1: + return stlink_read_option_bytes_gx(sl, option_byte); + case STM32_CHIPID_G0_CAT2: + return stlink_read_option_bytes_gx(sl, option_byte); + case STM32_CHIPID_G4_CAT2: + return stlink_read_option_bytes_gx(sl, option_byte); + case STM32_CHIPID_G4_CAT3: + return stlink_read_option_bytes_gx(sl, option_byte); + default: + return stlink_read_option_bytes_generic(sl, option_byte); + } } /** - * Write option bytes + * Write option bytes 32 * @param sl - * @param option bytes boot address to write + * @param option_byte * @return 0 on success, -ve on failure. */ -int stlink_write_option_bytes_boot_add32(stlink_t *sl, - uint32_t option_bytes_boot_add) { +int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) { + WLOG("About to write option byte %#10x to %#10x.\n", option_byte, + sl->option_base); + return stlink_write_option_bytes(sl, sl->option_base, (uint8_t *)&option_byte, 4); +} + +/** + * Read option bytes boot address 32 + * @param sl + * @param option_byte + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_bytes_boot_add32(stlink_t *sl, uint32_t *option_byte) { + if (sl->option_base == 0) { + ELOG("Option bytes boot address read is currently not supported for " + "connected chip\n"); + return -1; + } + + switch (sl->flash_type) { + case STM32_FLASH_TYPE_F7: + return stlink_read_option_bytes_boot_add_f7(sl, option_byte); + default: + return -1; + // return stlink_read_option_bytes_boot_add_generic(sl, option_byte); + } +} + +/** + * Write option bytes boot address 32 + * @param sl + * @param option_bytes_boot_add + * @return 0 on success, -ve on failure. + */ +int stlink_write_option_bytes_boot_add32(stlink_t *sl, uint32_t option_bytes_boot_add) { int ret = -1; wait_flash_busy(sl); @@ -961,175 +1107,3 @@ int stlink_write_option_bytes_boot_add32(stlink_t *sl, return ret; } - -/** - * Write option bytes - * @param sl - * @param option_byte value to write - * @return 0 on success, -ve on failure. - */ -int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte) { - WLOG("About to write option byte %#10x to %#10x.\n", option_byte, - sl->option_base); - return stlink_write_option_bytes(sl, sl->option_base, (uint8_t *)&option_byte, - 4); -} - -/** - * Write the given binary file with option bytes - * @param sl - * @param path readable file path, should be binary image - * @param addr of the memory mapped option bytes - * @return 0 on success, -ve on failure. - */ -int stlink_fwrite_option_bytes(stlink_t *sl, const char *path, - stm32_addr_t addr) { - /* Write the file in flash at addr */ - int err; - mapped_file_t mf = MAPPED_FILE_INITIALIZER; - - if (map_file(&mf, path) == -1) { - ELOG("map_file() == -1\n"); - return (-1); - } - - printf("file %s ", path); - md5_calculate(&mf); - stlink_checksum(&mf); - - err = stlink_write_option_bytes(sl, addr, mf.base, (uint32_t)mf.len); - stlink_fwrite_finalize(sl, addr); - unmap_file(&mf); - - return (err); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register1_f7(stlink_t *sl, - uint32_t *option_byte) { - DLOG("@@@@ Read option control register 1 byte from %#10x\n", - FLASH_F7_OPTCR1); - return stlink_read_debug32(sl, FLASH_F7_OPTCR1, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte option value - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register1_32(stlink_t *sl, - uint32_t *option_byte) { - if (sl->option_base == 0) { - ELOG("Option bytes read is currently not supported for connected chip\n"); - return -1; - } - - switch (sl->flash_type) { - case STM32_FLASH_TYPE_F7: - return stlink_read_option_control_register1_f7(sl, option_byte); - default: - return -1; - // return stlink_read_option_control_register1_generic(sl, option_byte); - } -} - - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_bytes_boot_add_f7(stlink_t *sl, uint32_t *option_byte) { - DLOG("@@@@ Read option byte boot address\n"); - return stlink_read_option_control_register1_f7(sl, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte option value - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_bytes_boot_add32(stlink_t *sl, uint32_t *option_byte) { - if (sl->option_base == 0) { - ELOG("Option bytes boot address read is currently not supported for " - "connected chip\n"); - return -1; - } - - switch (sl->flash_type) { - case STM32_FLASH_TYPE_F7: - return stlink_read_option_bytes_boot_add_f7(sl, option_byte); - default: - return -1; - // return stlink_read_option_bytes_boot_add_generic(sl, option_byte); - } -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register_f7(stlink_t *sl, - uint32_t *option_byte) { - DLOG("@@@@ Read option control register byte from %#10x\n", FLASH_F7_OPTCR); - return stlink_read_debug32(sl, FLASH_F7_OPTCR, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register_f0(stlink_t *sl, - uint32_t *option_byte) { - DLOG("@@@@ Read option control register byte from %#10x\n", FLASH_OBR); - return stlink_read_debug32(sl, FLASH_OBR, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte value to read - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register_wb(stlink_t *sl, - uint32_t *option_byte) { - DLOG("@@@@ Read option control register byte from %#10x\n", STM32WB_FLASH_OPTR); - return stlink_read_debug32(sl, STM32WB_FLASH_OPTR, option_byte); -} - -/** - * Read option bytes - * @param sl - * @param option_byte option value - * @return 0 on success, -ve on failure. - */ -int stlink_read_option_control_register32(stlink_t *sl, uint32_t *option_byte) { - if (sl->option_base == 0) { - ELOG("Option bytes read is currently not supported for connected chip\n"); - return -1; - } - - switch (sl->flash_type) { - case STM32_FLASH_TYPE_F0_F1_F3: - case STM32_FLASH_TYPE_F1_XL: - return stlink_read_option_control_register_f0(sl, option_byte); - case STM32_FLASH_TYPE_F7: - return stlink_read_option_control_register_f7(sl, option_byte); - case STM32_FLASH_TYPE_WB_WL: - return stlink_read_option_control_register_wb(sl, option_byte); - default: - return -1; - } -} diff --git a/src/stlink-lib/option_bytes.h b/src/stlink-lib/option_bytes.h new file mode 100644 index 0000000..b9f88c5 --- /dev/null +++ b/src/stlink-lib/option_bytes.h @@ -0,0 +1,21 @@ +/* + * File: option_bytes.h + * + * Read and write option bytes and option control registers + */ + +#include +#include + +int stlink_read_option_bytes32(stlink_t *sl, uint32_t* option_byte); +int stlink_read_option_bytes_boot_add32(stlink_t *sl, uint32_t* option_byte); +int stlink_read_option_control_register32(stlink_t *sl, uint32_t* option_byte); +int stlink_read_option_control_register1_32(stlink_t *sl, uint32_t* option_byte); + +int stlink_write_option_bytes32(stlink_t *sl, uint32_t option_byte); +int stlink_write_option_bytes_boot_add32(stlink_t *sl, uint32_t option_bytes_boot_add); +int stlink_write_option_control_register32(stlink_t *sl, uint32_t option_cr); +int stlink_write_option_control_register1_32(stlink_t *sl, uint32_t option_cr1); + +int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len); +int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr); diff --git a/src/read_write.c b/src/stlink-lib/read_write.c similarity index 100% rename from src/read_write.c rename to src/stlink-lib/read_write.c