From 29a36a2d7b93bcbc718def96209ca981aa2ef353 Mon Sep 17 00:00:00 2001 From: Marek Kraus Date: Sun, 25 Sep 2022 10:58:59 +0200 Subject: [PATCH] WIP --- CMakeLists.txt | 73 ++++++++++-------- README.md | 3 +- include/blisp.h | 29 +++++++ include/blisp_chip.h | 18 +++++ include/blisp_easy.h | 6 -- lib/blisp.c | 148 ++++++++++++++++++++++++++++++++++++ lib/blisp_easy.c | 1 - lib/chip/blisp_chip_bl70x.c | 6 ++ tools/blisp/CMakeLists.txt | 6 +- tools/blisp/src/cmd/write.c | 38 +++++++-- 10 files changed, 277 insertions(+), 51 deletions(-) create mode 100644 include/blisp.h create mode 100644 include/blisp_chip.h delete mode 100644 include/blisp_easy.h create mode 100644 lib/blisp.c delete mode 100644 lib/blisp_easy.c create mode 100644 lib/chip/blisp_chip_bl70x.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 944fd50..992e7a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,47 +4,54 @@ project(blisp C) set(CMAKE_C_STANDARD 23) option(BLISP_BUILD_CLI "Build CLI Tool" OFF) -option(BLISP_DYNAMIC_LIBRARY "Build dynamic library" OFF) -if(BLISP_DYNAMIC_LIBRARY) - add_library(libblisp SHARED) -else() - add_library(libblisp STATIC) -endif() +add_library(libblisp_obj OBJECT + lib/blisp.c + lib/chip/blisp_chip_bl70x.c) -target_sources(libblisp PRIVATE lib/blisp_easy.c) +target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/include/) + +set_property(TARGET libblisp_obj PROPERTY POSITION_INDEPENDENT_CODE 1) + +add_library(libblisp SHARED $) +add_library(libblisp_static STATIC $) -target_include_directories(libblisp PRIVATE ${CMAKE_SOURCE_DIR}/include/) set_target_properties(libblisp PROPERTIES - PUBLIC_HEADER "include/blisp_easy.h" + PUBLIC_HEADER "include/blisp.h" VERSION 1.0 SOVERSION 1 - OUTPUT_NAME "blisp" -) + LIBRARY_OUTPUT_DIRECTORY "shared" + OUTPUT_NAME "blisp") + +set_target_properties(libblisp_static PROPERTIES + PUBLIC_HEADER "include/blisp.h" + VERSION 1.0 + SOVERSION 1 + ARCHIVE_OUTPUT_DIRECTORY "static" + OUTPUT_NAME "blisp") + +target_sources(libblisp_obj PRIVATE + ${CMAKE_SOURCE_DIR}/vendor/libserialport/serialport.c + ${CMAKE_SOURCE_DIR}/vendor/libserialport/timing.c) + +if(WIN32) + target_link_libraries(libblisp_obj PRIVATE Setupapi.lib) + target_compile_definitions(libblisp_obj PRIVATE LIBSERIALPORT_MSBUILD) + target_sources(libblisp_obj PRIVATE + ${CMAKE_SOURCE_DIR}/vendor/libserialport/windows.c) +elseif(UNIX AND NOT APPLE) + target_sources(libblisp_obj PRIVATE + ${CMAKE_SOURCE_DIR}/vendor/libserialport/linux.c + ${CMAKE_SOURCE_DIR}/vendor/libserialport/linux_termios.c) + target_compile_definitions(libblisp_obj PRIVATE + LIBSERIALPORT_ATBUILD + "SP_API=__attribute__((visibility(\"default\")))" + "SP_PRIV=__attribute__((visibility(\"hidden\")))") + target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/vendor/libserialport) + write_file(${CMAKE_SOURCE_DIR}/vendor/libserialport/config.h "// bypass errors.") +endif() if(BLISP_BUILD_CLI) add_subdirectory(tools/blisp) endif() - - -#target_sources(blisp PRIVATE -# ${CMAKE_SOURCE_DIR}/vendor/libserialport/serialport.c -# ${CMAKE_SOURCE_DIR}/vendor/libserialport/timing.c) -# -#if(WIN32) -# target_link_libraries(blisp PRIVATE Setupapi.lib) -# target_compile_definitions(blisp PRIVATE LIBSERIALPORT_MSBUILD) -# target_sources(blisp PRIVATE -# ${CMAKE_SOURCE_DIR}/vendor/libserialport/windows.c) -#elseif(UNIX AND NOT APPLE) -# target_sources(blisp PRIVATE -# ${CMAKE_SOURCE_DIR}/vendor/libserialport/linux.c -# ${CMAKE_SOURCE_DIR}/vendor/libserialport/linux_termios.c) -# target_compile_definitions(blisp PRIVATE -# LIBSERIALPORT_ATBUILD -# "SP_API=__attribute__((visibility(\"default\")))" -# "SP_PRIV=__attribute__((visibility(\"hidden\")))") -# target_include_directories(blisp PRIVATE ${CMAKE_SOURCE_DIR}/vendor/libserialport) -# write_file(${CMAKE_SOURCE_DIR}/vendor/libserialport/config.h "// bypass errors.") -#endif() \ No newline at end of file diff --git a/README.md b/README.md index 671a1e6..57ebf5a 100644 --- a/README.md +++ b/README.md @@ -13,4 +13,5 @@ Tool and library for flashing their RISC-V MCUs. # To Do - [ ] Another code style -- [ ] Separate `blisp` flashing to library \ No newline at end of file +- [ ] Finalize API +- [ ] SDIO and JTAG support \ No newline at end of file diff --git a/include/blisp.h b/include/blisp.h new file mode 100644 index 0000000..af6cb04 --- /dev/null +++ b/include/blisp.h @@ -0,0 +1,29 @@ +#ifndef _LIBBLISP_H +#define _LIBBLISP_H + +#include + +#include "blisp_chip.h" + +struct blisp_device { + struct blisp_chip* chip; + void* serial_port; + bool is_usb; + uint32_t current_baud_rate; + uint8_t rx_buffer[5000]; // TODO: + uint8_t tx_buffer[5000]; + uint16_t error_code; +}; + +struct blisp_boot_info { + uint8_t boot_rom_version[4]; + uint8_t chip_id[8]; // TODO: BL60X only 6 bytes +}; + +int32_t blisp_device_init(struct blisp_device* device, struct blisp_chip* chip); +int32_t blisp_device_open(struct blisp_device* device, const char* port_name); +int32_t blisp_device_handshake(struct blisp_device* device); +int32_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boot_info* boot_info); +void blisp_device_close(struct blisp_device* device); + +#endif \ No newline at end of file diff --git a/include/blisp_chip.h b/include/blisp_chip.h new file mode 100644 index 0000000..ddd27cf --- /dev/null +++ b/include/blisp_chip.h @@ -0,0 +1,18 @@ +#ifndef _BLISP_CHIP_H +#define _BLISP_CHIP_H + +#include +#include + +enum blisp_chip_type { + BLISP_CHIP_BL70X +}; + +struct blisp_chip { // TODO: Move elsewhere? + enum blisp_chip_type type; + bool usb_isp_available; +}; + +extern struct blisp_chip blisp_chip_bl70x; + +#endif \ No newline at end of file diff --git a/include/blisp_easy.h b/include/blisp_easy.h deleted file mode 100644 index f59dad9..0000000 --- a/include/blisp_easy.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _LIBBLISP_EASY_H -#define _LIBBLISP_EASY_H - - - -#endif \ No newline at end of file diff --git a/lib/blisp.c b/lib/blisp.c new file mode 100644 index 0000000..bafc6d6 --- /dev/null +++ b/lib/blisp.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include + +int32_t blisp_device_init(struct blisp_device* device, struct blisp_chip* chip) +{ + device->chip = chip; + device->is_usb = false; + return 0; +} + +int32_t blisp_device_open(struct blisp_device* device, const char* port_name) +{ + int ret; + struct sp_port* serial_port = NULL; + + if (port_name != NULL) { + ret = sp_get_port_by_name(port_name, &serial_port); + if (ret != SP_OK) { + return -1; // TODO: Improve error codes + } + } else { + if (!device->chip->usb_isp_available) { + return -2; // Can't auto-find device due it doesn't have native USB + } + struct sp_port **port_list; + ret = sp_list_ports(&port_list); + if (ret != SP_OK) { + return -1; // TODO: Improve error codes + } + for (int i = 0; port_list[i] != NULL; i++) { + struct sp_port *port = port_list[i]; + + int vid, pid; + sp_get_port_usb_vid_pid(port, &vid, &pid); + if (vid == 0xFFFF && pid == 0xFFFF) { + ret = sp_get_port_by_name(sp_get_port_name(port), &serial_port); + if (ret != SP_OK) { + return -1; // TODO: Improve error codes + } + break; + } + } + sp_free_port_list(port_list); + if (serial_port == NULL) { + return -3; // Device not found + } + } + + ret = sp_open(serial_port, SP_MODE_READ_WRITE); + if (ret != SP_OK) { // TODO: Handle not found + return -1; + } + sp_set_bits(serial_port, 8); + sp_set_parity(serial_port, SP_PARITY_NONE); + sp_set_stopbits(serial_port, 1); + sp_set_flowcontrol(serial_port, SP_FLOWCONTROL_NONE); + uint32_t vid, pid; + sp_get_port_usb_vid_pid(serial_port, &vid, &pid); + device->is_usb = pid == 0xFFFF; + if (device->is_usb) { + device->current_baud_rate = 2000000; + } else { + device->current_baud_rate = 500000; + } + sp_set_baudrate(serial_port, device->current_baud_rate); + device->serial_port = serial_port; + return 0; +} + +int32_t blisp_send_command(struct blisp_device* device, uint8_t command, void* payload, uint16_t payload_size, bool add_checksum) +{ + int ret; + struct sp_port* serial_port = device->serial_port; + + device->tx_buffer[0] = command; + device->tx_buffer[1] = 0; + device->tx_buffer[2] = (payload_size >> 8) & 0xFF; + device->tx_buffer[3] = payload_size & 0xFF; + if (add_checksum) { + uint32_t checksum = 0; + checksum += device->tx_buffer[2] + device->tx_buffer[3]; + for (uint16_t i = 0; i < payload_size; i++) { + checksum += *(uint8_t*)(payload + i); + } + device->tx_buffer[1] = checksum & 0xFF; + } + if (payload_size != 0) { + memcpy(&device->tx_buffer[4], payload, payload_size); + } + ret = sp_blocking_write(serial_port, device->tx_buffer, 4 + payload_size, 1000); + if (ret != (4 + payload_size)) { + return -1; + } + return 0; +} + +int32_t blisp_receive_response(struct blisp_device* device, bool expect_payload) { + int ret; + struct sp_port* serial_port = device->serial_port; + ret = sp_blocking_read(serial_port, &device->rx_buffer[0], 2, 300); + if (ret < 2) { + return -1; + } + +} + +int32_t blisp_device_handshake(struct blisp_device* device) +{ + int ret; + uint8_t handshake_buffer[600]; + struct sp_port* serial_port = device->serial_port; + + if (device->is_usb) { + sp_blocking_write(serial_port, "BOUFFALOLAB5555RESET\0\0", 22, 100); + } + uint32_t bytes_count = 0.003f * (float)device->current_baud_rate / 10.0f; // TODO: 0.003f is only for BL70X! + if (bytes_count > 600) bytes_count = 600; + memset(handshake_buffer, 'U', bytes_count); + ret = sp_blocking_write(serial_port, handshake_buffer, bytes_count, 100); + if (ret < 0) { + return -1; + } + ret = sp_blocking_read(serial_port, device->rx_buffer, 2, 100); + if (ret < 2 || device->rx_buffer[0] != 'O' || device->rx_buffer[1] != 'K') { + return -4; // didn't received response + } + return 0; +} + +int32_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boot_info* boot_info) +{ + int ret; + + ret = blisp_send_command(device, 0x10, NULL, 0, false); + if (ret < 0) return ret; + + ret = blisp_receive_response(device, true); + + return 0; +} + +void blisp_device_close(struct blisp_device* device) +{ + struct sp_port* serial_port = device->serial_port; + sp_close(serial_port); +} \ No newline at end of file diff --git a/lib/blisp_easy.c b/lib/blisp_easy.c deleted file mode 100644 index 09458c6..0000000 --- a/lib/blisp_easy.c +++ /dev/null @@ -1 +0,0 @@ -#include \ No newline at end of file diff --git a/lib/chip/blisp_chip_bl70x.c b/lib/chip/blisp_chip_bl70x.c new file mode 100644 index 0000000..f62f905 --- /dev/null +++ b/lib/chip/blisp_chip_bl70x.c @@ -0,0 +1,6 @@ +#include "blisp.h" + +struct blisp_chip blisp_chip_bl70x = { + .type = BLISP_CHIP_BL70X, + .usb_isp_available = true +}; diff --git a/tools/blisp/CMakeLists.txt b/tools/blisp/CMakeLists.txt index 027d131..235d8c5 100644 --- a/tools/blisp/CMakeLists.txt +++ b/tools/blisp/CMakeLists.txt @@ -5,6 +5,8 @@ add_executable(blisp src/main.c src/cmd/write.c) target_include_directories(blisp PRIVATE "${CMAKE_SOURCE_DIR}/include" "${CMAKE_SOURCE_DIR}/vendor/argtable3/src") + target_link_libraries(blisp PRIVATE - libblisp - argtable3) \ No newline at end of file + argtable3 + libblisp_static) + diff --git a/tools/blisp/src/cmd/write.c b/tools/blisp/src/cmd/write.c index c26ce24..b4e4e77 100644 --- a/tools/blisp/src/cmd/write.c +++ b/tools/blisp/src/cmd/write.c @@ -1,18 +1,38 @@ #include "../cmd.h" #include "argtable3.h" - -void blisp_flash_firmware(const char* firmware_path) { - printf(""); -} - +#include #define REG_EXTENDED 1 #define REG_ICASE (REG_EXTENDED << 1) static struct arg_rex* cmd; static struct arg_file* binary_to_write; +static struct arg_str* port_name; static struct arg_end* end; -static void* cmd_write_argtable[3]; +static void* cmd_write_argtable[4]; + +void blisp_flash_firmware() { + struct blisp_device device; + uint32_t ret; + ret = blisp_device_init(&device, &blisp_chip_bl70x); + if (ret != 0) { + fprintf(stderr, "Failed to init device.\n"); + return; + } + ret = blisp_device_open(&device, port_name->count == 1 ? port_name->sval[0] : NULL); + if (ret != 0) { + fprintf(stderr, "Failed to open device.\n"); + return; + } + printf("Sending a handshake..."); + ret = blisp_device_handshake(&device); + if (ret != 0) { + fprintf(stderr, "\nFailed to handshake with device.\n"); + return; + } + printf(" OK\n"); + blisp_device_close(&device); +} int8_t cmd_write_args_init() { @@ -20,7 +40,9 @@ cmd_write_args_init() { = arg_rex1(NULL, NULL, "write", NULL, REG_ICASE, NULL); cmd_write_argtable[1] = binary_to_write = arg_file1(NULL, NULL, "", "Binary to write"); - cmd_write_argtable[2] = end = arg_end(10); + cmd_write_argtable[2] = port_name + = arg_str0("p", "port", "", "Name/Path to the Serial Port (empty for search)"); + cmd_write_argtable[3] = end = arg_end(10); if (arg_nullcheck(cmd_write_argtable) != 0) { fprintf(stderr, "insufficient memory\n"); @@ -40,7 +62,7 @@ uint8_t cmd_write_parse_exec(int argc, char** argv) { int errors = arg_parse(argc, argv, cmd_write_argtable); if (errors == 0) { - blisp_flash_firmware(binary_to_write->filename[0]); // TODO: Error code? + blisp_flash_firmware(); // TODO: Error code? return 1; } else if (cmd->count == 1) { cmd_write_args_print_glossary();