4 Commits
Author SHA1 Message Date
Terence Noone 6cece6970b Merge 5634b678f3 into d51e7bcc1e 2024-12-02 17:34:40 -06:00
Terence Noone 5634b678f3 Fix linking with argtable3
CMake interpreted `argtable3` to mean add `-largtable3` rather than to
use the imported argtable3 target. This worked when using the bundled
library, but broke with native libraries.
2024-03-03 00:46:22 -05:00
Terence Noone 8dbb58353b Do not build for both arm64 and x86_84 on macOS.
While this might work when using bundled libraries, this breaks with
system libraries as they are all compiled for arm64. Also, why would you
need to compile an x86_64 version on arm64, and vise versa.
2024-03-03 00:41:37 -05:00
Terence Noone f1fcdb9587 Use new find module for libserialport
This new find module will replace the old logic used to locate a native
copy of libserialport. THe old code didn't work on macOS, and was pretty
messy.
2024-03-03 00:41:29 -05:00
36 changed files with 253 additions and 1499 deletions
+18 -44
View File
@@ -24,9 +24,9 @@ jobs:
run:
shell: cmd
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
submodules: "recursive"
submodules: 'recursive'
- uses: lukka/get-cmake@latest
- name: Build blisp tool
run: |
@@ -35,9 +35,9 @@ jobs:
cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
- name: Upload results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: blips-windows-x86_64
name: blips-windows-x86_64.zip
path: |
build/tools/blisp/Release/blisp.exe
if-no-files-found: error
@@ -45,9 +45,9 @@ jobs:
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
submodules: "recursive"
submodules: 'recursive'
- uses: lukka/get-cmake@latest
- name: Build blisp tool
run: |
@@ -56,9 +56,9 @@ jobs:
cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build .
- name: Upload results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: blips-apple-universal
name: blips-apple-universal.zip
path: |
build/tools/blisp/blisp
if-no-files-found: error
@@ -66,9 +66,9 @@ jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
submodules: "recursive"
submodules: 'recursive'
- uses: lukka/get-cmake@latest
- name: Build blisp tool
run: |
@@ -77,12 +77,12 @@ jobs:
cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build .
- name: Upload results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: blips-linux-x86_64
name: blips-linux-x86_64.zip
path: |
build/tools/blisp/blisp
if-no-files-found: error
if-no-files-found: error
build-linux-alternative-arch:
runs-on: ubuntu-latest
@@ -99,9 +99,9 @@ jobs:
- arch: riscv64
distro: ubuntu_latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
submodules: "recursive"
submodules: 'recursive'
- uses: uraimo/run-on-arch-action@v2
name: Build artifact
id: build
@@ -149,35 +149,9 @@ jobs:
echo "Produced artifact at /artifacts/${artifact_name}"
- name: Upload results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: blisp-linux-${{ matrix.arch }}
name: blisp-linux-${{ matrix.arch }}.zip
path: |
artifacts/blisp-*
if-no-files-found: error
test-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: "recursive"
- uses: lukka/get-cmake@latest
- name: Build blisp tool & unit tests
run: |
mkdir build
cd build
cmake .. -DBLISP_BUILD_CLI=ON -DCOMPILE_TESTS=ON
cmake --build .
- name: Run unit tests
run: |
cd build
for f in $(find . -type f -executable -iname "*_test"); do
echo "Running test file $f"
"$f"
status=$?
if [ $status -ne 0 ]; then
echo "Test $f failed with exit code $status"
exit $status
fi
done
if-no-files-found: error
+1 -2
View File
@@ -77,5 +77,4 @@ fabric.properties
.idea/caches/build_file_checksums.ser
build/
.DS_Store
.cache/
.DS_Store
+9 -37
View File
@@ -11,22 +11,10 @@ option(COMPILE_TESTS "Compile the tests" OFF)
add_library(libblisp_obj OBJECT
lib/blisp.c
lib/blisp_easy.c
lib/blisp_util.c
lib/chip/blisp_chip_bl60x.c
lib/chip/blisp_chip_bl70x.c
lib/chip/blisp_chip_bl808.c)
lib/chip/blisp_chip_bl70x.c lib/blisp_easy.c)
target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/include/)
if (NOT CMAKE_C_COMPILER_ID MATCHES "MSVC")
target_compile_options(libblisp_obj PRIVATE -Wall -Wextra -Wpedantic)
else()
# MSVC does not support 'extra' and 'pedantic' levels to warnings.
# `/Wall` seems to generate way too many non-actionable output marked as warnings.
# We settle for `/W4`.
# https://learn.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level?view=msvc-170
target_compile_options(libblisp_obj PRIVATE -W4)
endif()
set_property(TARGET libblisp_obj PROPERTY POSITION_INDEPENDENT_CODE 1)
@@ -42,14 +30,14 @@ set(BLISP_PUBLIC_HEADERS
set_target_properties(libblisp PROPERTIES
PUBLIC_HEADER "${BLISP_PUBLIC_HEADERS}"
VERSION 0.0.5
VERSION 0.0.4
SOVERSION 1
LIBRARY_OUTPUT_DIRECTORY "shared"
OUTPUT_NAME "blisp")
set_target_properties(libblisp_static PROPERTIES
PUBLIC_HEADER "${BLISP_PUBLIC_HEADERS}"
VERSION 0.0.5
VERSION 0.0.4
SOVERSION 1
ARCHIVE_OUTPUT_DIRECTORY "static"
OUTPUT_NAME "blisp")
@@ -60,13 +48,13 @@ if(BLISP_USE_SYSTEM_LIBRARIES)
target_link_libraries(libblisp_static PUBLIC Libserialport::Libserialport)
target_include_directories(libblisp_obj PUBLIC ${Libserialport_INCLUDE_DIRS})
else()
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
target_sources(libblisp_obj PRIVATE
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
target_sources(libblisp_obj PRIVATE
${CMAKE_SOURCE_DIR}/vendor/libserialport/serialport.c
${CMAKE_SOURCE_DIR}/vendor/libserialport/timing.c)
target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/vendor/libserialport)
endif()
target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/vendor/libserialport)
endif()
if(WIN32)
target_link_libraries(libblisp PRIVATE Setupapi.lib)
@@ -104,7 +92,7 @@ else()
endif()
include(GNUInstallDirs)
install(TARGETS libblisp libblisp_static
install(TARGETS libblisp libblisp_static
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -117,21 +105,5 @@ endif()
if(COMPILE_TESTS)
# Bring in googletest & C++
enable_language(CXX)
enable_testing()
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.17.0
)
FetchContent_MakeAvailable(googletest)
add_library(GTest::GTest INTERFACE IMPORTED)
target_link_libraries(GTest::GTest INTERFACE gtest_main)
add_subdirectory(tools/blisp/src/file_parsers/dfu/tests)
add_subdirectory(tools/blisp/src/file_parsers/hex/tests)
add_subdirectory(tools/blisp/src/cmd/dfu/tests)
endif(COMPILE_TESTS)
-35
View File
@@ -1,35 +0,0 @@
#!/usr/bin/env make -f
### global variables section
# static vars
BUILD_DIR:="build"
BUILD_BIN:="$(BUILD_DIR)/tools/blisp/blisp"
# dynamic vars
FILES_CMAKE:=$(shell find . -path ./$(BUILD_DIR) -prune -false -o -type f -name '*.cmake' -o -type f -name 'CMakeLists.txt')
FILES_SRC:=$(shell find . -path ./$(BUILD_DIR) -prune -false -o -type f -name '*.c' -o -type f -name '*.h')
### main targets section
# simplify build
build: $(FILES_CMAKE) $(FILES_SRC) Makefile
@echo "\n>>>> Generating build files in: $(BUILD_DIR) ...\n"
@cmake -S . -B $(BUILD_DIR) -DBLISP_BUILD_CLI=ON
@echo "\n>>>> Building...\n"
@cmake --build $(BUILD_DIR)
@echo "\n>>>> DONE: $(BUILD_BIN)\n"
# deleting output build directory with its content
clean:
-@rm -rf $(BUILD_DIR)/
# printf-like debug target
vars:
@echo "\n>>>> FILES_CMAKE:"
@echo "$(FILES_CMAKE)" | sed 's, ,\n,g'
@echo "\n>>>> FILES_SRC:"
@echo "$(FILES_SRC)" | sed 's, ,\n,g'
.PHONY: clean vars
+6 -15
View File
@@ -1,10 +1,10 @@
[![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fpine64%2Fblisp&count_bg=%235791AC&title_bg=%23555555&icon=airplayaudio.svg&icon_color=%23D2D9DD&title=hits&edge_flat=false)](https://github.com/pine64/blisp/wiki/Update-Pinecil-V2)
[![GitHub all downloads](https://img.shields.io/github/downloads/pine64/blisp/total?color=5791ac&logo=docusign&logoColor=white)](https://github.com/pine64/blisp/releases/tag/v0.0.5)
[![GitHub all downloads](https://img.shields.io/github/downloads/pine64/blisp/total?color=5791ac&logo=docusign&logoColor=white)](https://github.com/pine64/blisp/releases/tag/v0.0.4)
[![Discord](https://img.shields.io/discord/463237927984693259?color=5791ac&logo=discord&logoColor=white)](https://discord.com/invite/pine64)
[![GitHub release](https://img.shields.io/github/v/release/pine64/blisp?color=5791ac)](https://github.com/pine64/blisp/releases/tag/v0.0.5)
[![GitHub release](https://img.shields.io/github/v/release/pine64/blisp?color=5791ac)](https://github.com/pine64/blisp/releases/tag/v0.0.4)
<img src="./img/Gradient-white-blue-03.png" align="left" width="60" > <br clear="left" />
# BLISP
# BLISP
Bouffalo Labs ISP (in-system-programming) tool & library: an open source tool to flash Bouffalo RISC-V MCUs.
@@ -16,13 +16,13 @@ Bouffalo Labs ISP (in-system-programming) tool & library: an open source tool to
- [x] `bl70x` - BL702 / BL704 / BL706
<br>
## Supported Devices
| System | <img width="15" src="img/win32.png" /> Windows | <img width="15" src="https://cdn.simpleicons.org/Apple/5791ac" /> MacOS| <img width="17" src="https://cdn.simpleicons.org/Linux/5791ac" /> Linux| <img width="15" src="https://cdn.simpleicons.org/Freebsd/5791ac" /> FreeBSD |
## Supported Devices
| System | <img width="15" src="https://cdn.simpleicons.org/Windows11/5791ac" /> Windows | <img width="15" src="https://cdn.simpleicons.org/Apple/5791ac" /> MacOS| <img width="17" src="https://cdn.simpleicons.org/Linux/5791ac" /> Linux| <img width="15" src="https://cdn.simpleicons.org/Freebsd/5791ac" /> FreeBSD |
| :-----: | :------: | :------: | :------: | :------: |
| Pinecil V2 |<img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" />|<img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" />| <img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" />| <img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" /> |
| Pinecone |<img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" />|<img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" />|<img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" />| <img width="22" src="https://cdn.simpleicons.org/cachet/5791ac" /> |
<br>
## How to update Pinecil V2
Download the newest release of [Blisp updater here](https://github.com/pine64/blisp/releases/).
@@ -94,15 +94,6 @@ Because this is done at the lowest level of serial communication, the
displays aren't packet-aware or know about the chip's command set or such.
This is really only useful for debugging systems-level issues withing
the device or blisp itself.
## Running unit tests
```shell
mkdir build && cd build
cmake -DBLISP_BUILD_CLI=ON -DCOMPILE_TESTS=ON ..
cmake --build .
# Find all compiled unit test files; you can now run these directly
find . -type f -executable -iname "*_test" -print
```
## Troubleshooting
+1 -1
View File
@@ -13,7 +13,7 @@
stdenv.mkDerivation (finalAttrs: {
pname = "blisp";
version = "0.0.5-unstable";
version = "0.0.4-unstable";
src = self;
nativeBuildInputs = [
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 B

+27 -36
View File
@@ -16,7 +16,6 @@ struct blisp_segment_header {
struct blisp_device {
struct blisp_chip* chip;
void* serial_port;
uint32_t serial_timeout; // in ms
bool is_usb;
uint32_t current_baud_rate;
uint8_t rx_buffer[5000]; // TODO:
@@ -32,42 +31,34 @@ struct blisp_boot_info {
// TODO: Refactor variable names, so all will follow same semantic, like
// image_run, image_check etc.
blisp_return_t blisp_device_init(struct blisp_device* device, struct blisp_chip* chip);
blisp_return_t blisp_device_open(struct blisp_device* device, const char* port_name,
uint32_t baudrate);
blisp_return_t blisp_device_handshake(struct blisp_device* device, bool in_ef_loader);
blisp_return_t blisp_device_get_boot_info(struct blisp_device* device,
struct blisp_boot_info* boot_info);
blisp_return_t blisp_device_load_boot_header(struct blisp_device* device,
uint8_t* boot_header);
blisp_return_t blisp_device_load_segment_header(
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, bool in_ef_loader);
int32_t blisp_device_get_boot_info(struct blisp_device* device,
struct blisp_boot_info* boot_info);
int32_t blisp_device_load_boot_header(struct blisp_device* device,
uint8_t* boot_header);
int32_t blisp_device_load_segment_header(
struct blisp_device* device,
struct blisp_segment_header* segment_header);
blisp_return_t blisp_device_load_segment_data(struct blisp_device* device,
uint8_t* segment_data,
uint32_t segment_data_length);
blisp_return_t blisp_device_write_memory(struct blisp_device* device,
uint32_t address,
uint32_t value,
bool wait_for_res);
blisp_return_t blisp_device_check_image(struct blisp_device* device);
blisp_return_t blisp_device_run_image(struct blisp_device* device);
blisp_return_t blisp_device_flash_erase(struct blisp_device* device,
uint32_t start_address,
uint32_t end_address);
blisp_return_t blisp_device_chip_erase(struct blisp_device* device);
blisp_return_t blisp_device_flash_write(struct blisp_device* device,
uint32_t start_address,
uint8_t* payload,
uint32_t payload_size);
blisp_return_t blisp_device_program_check(struct blisp_device* device);
blisp_return_t blisp_device_reset(struct blisp_device* device);
int32_t blisp_device_load_segment_data(struct blisp_device* device,
uint8_t* segment_data,
uint32_t segment_data_length);
int32_t blisp_device_write_memory(struct blisp_device* device,
uint32_t address,
uint32_t value,
bool wait_for_res);
int32_t blisp_device_check_image(struct blisp_device* device);
int32_t blisp_device_run_image(struct blisp_device* device);
int32_t blisp_device_flash_erase(struct blisp_device* device,
uint32_t start_address,
uint32_t end_address);
int32_t blisp_device_flash_write(struct blisp_device* device,
uint32_t start_address,
uint8_t* payload,
uint32_t payload_size);
int32_t blisp_device_program_check(struct blisp_device* device);
int32_t blisp_device_reset(struct blisp_device* device);
void blisp_device_close(struct blisp_device* device);
blisp_return_t bl808_load_clock_para(struct blisp_device* device,
bool irq_en, uint32_t baudrate);
blisp_return_t bl808_load_flash_para(struct blisp_device* device);
#endif
#endif
+1 -4
View File
@@ -28,7 +28,4 @@ extern struct blisp_chip blisp_chip_bl70x;
extern struct blisp_chip blisp_chip_bl808;
extern struct blisp_chip blisp_chip_bl61x;
extern struct bl808_bootheader_t bl808_header;
void fill_crcs(struct bl808_bootheader_t *bh);
#endif
#endif
-212
View File
@@ -9,12 +9,6 @@
#include <assert.h>
#include <stdint.h>
#if !defined(static_assert) && (defined(__GNUC__) || defined(__clang__)) \
&& defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
&& __STDC_VERSION__ <= 201710L
#define static_assert _Static_assert
#endif
#pragma pack(push, 1)
typedef struct {
@@ -173,212 +167,6 @@ struct blflash_segment_header {
static_assert(sizeof(struct blflash_segment_header) == 16,
"Segment header have wrong size");
struct bl808_spi_flash_cfg_t {
uint8_t ioMode; /*!< Serail flash interface mode,bit0-3:IF mode,bit4:unwrap */
uint8_t cReadSupport; /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */
uint8_t clkDelay; /*!< SPI clock delay,bit0-3:delay,bit4-6:pad delay */
uint8_t clkInvert; /*!< SPI clock phase invert,bit0:clck invert,bit1:rx invert,bit2-4:pad delay,bit5-7:pad delay */
uint8_t resetEnCmd; /*!< Flash enable reset command */
uint8_t resetCmd; /*!< Flash reset command */
uint8_t resetCreadCmd; /*!< Flash reset continuous read command */
uint8_t resetCreadCmdSize; /*!< Flash reset continuous read command size */
uint8_t jedecIdCmd; /*!< JEDEC ID command */
uint8_t jedecIdCmdDmyClk; /*!< JEDEC ID command dummy clock */
uint8_t enter32BitsAddrCmd; /*!< Enter 32-bits addr command */
uint8_t exit32BitsAddrCmd; /*!< Exit 32-bits addr command */
uint8_t sectorSize; /*!< *1024bytes */
uint8_t mid; /*!< Manufacturer ID */
uint16_t pageSize; /*!< Page size */
uint8_t chipEraseCmd; /*!< Chip erase cmd */
uint8_t sectorEraseCmd; /*!< Sector erase command */
uint8_t blk32EraseCmd; /*!< Block 32K erase command,some Micron not support */
uint8_t blk64EraseCmd; /*!< Block 64K erase command */
uint8_t writeEnableCmd; /*!< Need before every erase or program */
uint8_t pageProgramCmd; /*!< Page program cmd */
uint8_t qpageProgramCmd; /*!< QIO page program cmd */
uint8_t qppAddrMode; /*!< QIO page program address mode */
uint8_t fastReadCmd; /*!< Fast read command */
uint8_t frDmyClk; /*!< Fast read command dummy clock */
uint8_t qpiFastReadCmd; /*!< QPI fast read command */
uint8_t qpiFrDmyClk; /*!< QPI fast read command dummy clock */
uint8_t fastReadDoCmd; /*!< Fast read dual output command */
uint8_t frDoDmyClk; /*!< Fast read dual output command dummy clock */
uint8_t fastReadDioCmd; /*!< Fast read dual io comamnd */
uint8_t frDioDmyClk; /*!< Fast read dual io command dummy clock */
uint8_t fastReadQoCmd; /*!< Fast read quad output comamnd */
uint8_t frQoDmyClk; /*!< Fast read quad output comamnd dummy clock */
uint8_t fastReadQioCmd; /*!< Fast read quad io comamnd */
uint8_t frQioDmyClk; /*!< Fast read quad io comamnd dummy clock */
uint8_t qpiFastReadQioCmd; /*!< QPI fast read quad io comamnd */
uint8_t qpiFrQioDmyClk; /*!< QPI fast read QIO dummy clock */
uint8_t qpiPageProgramCmd; /*!< QPI program command */
uint8_t writeVregEnableCmd; /*!< Enable write reg */
uint8_t wrEnableIndex; /*!< Write enable register index */
uint8_t qeIndex; /*!< Quad mode enable register index */
uint8_t busyIndex; /*!< Busy status register index */
uint8_t wrEnableBit; /*!< Write enable bit pos */
uint8_t qeBit; /*!< Quad enable bit pos */
uint8_t busyBit; /*!< Busy status bit pos */
uint8_t wrEnableWriteRegLen; /*!< Register length of write enable */
uint8_t wrEnableReadRegLen; /*!< Register length of write enable status */
uint8_t qeWriteRegLen; /*!< Register length of contain quad enable */
uint8_t qeReadRegLen; /*!< Register length of contain quad enable status */
uint8_t releasePowerDown; /*!< Release power down command */
uint8_t busyReadRegLen; /*!< Register length of contain busy status */
uint8_t readRegCmd[4]; /*!< Read register command buffer */
uint8_t writeRegCmd[4]; /*!< Write register command buffer */
uint8_t enterQpi; /*!< Enter qpi command */
uint8_t exitQpi; /*!< Exit qpi command */
uint8_t cReadMode; /*!< Config data for continuous read mode */
uint8_t cRExit; /*!< Config data for exit continuous read mode */
uint8_t burstWrapCmd; /*!< Enable burst wrap command */
uint8_t burstWrapCmdDmyClk; /*!< Enable burst wrap command dummy clock */
uint8_t burstWrapDataMode; /*!< Data and address mode for this command */
uint8_t burstWrapData; /*!< Data to enable burst wrap */
uint8_t deBurstWrapCmd; /*!< Disable burst wrap command */
uint8_t deBurstWrapCmdDmyClk; /*!< Disable burst wrap command dummy clock */
uint8_t deBurstWrapDataMode; /*!< Data and address mode for this command */
uint8_t deBurstWrapData; /*!< Data to disable burst wrap */
uint16_t timeEsector; /*!< 4K erase time */
uint16_t timeE32k; /*!< 32K erase time */
uint16_t timeE64k; /*!< 64K erase time */
uint16_t timePagePgm; /*!< Page program time */
uint16_t timeCe; /*!< Chip erase time in ms */
uint8_t pdDelay; /*!< Release power down command delay time for wake up */
uint8_t qeData; /*!< QE set data */
};
struct bl808_boot_flash_cfg_t {
uint32_t magiccode;
struct bl808_spi_flash_cfg_t cfg;
uint32_t crc32;
};
struct bl808_sys_clk_cfg_t {
uint8_t xtal_type;
uint8_t mcu_clk;
uint8_t mcu_clk_div;
uint8_t mcu_bclk_div;
uint8_t mcu_pbclk_div;
uint8_t lp_div;
uint8_t dsp_clk;
uint8_t dsp_clk_div;
uint8_t dsp_bclk_div;
uint8_t dsp_pbclk;
uint8_t dsp_pbclk_div;
uint8_t emi_clk;
uint8_t emi_clk_div;
uint8_t flash_clk_type;
uint8_t flash_clk_div;
uint8_t wifipll_pu;
uint8_t aupll_pu;
uint8_t cpupll_pu;
uint8_t mipipll_pu;
uint8_t uhspll_pu;
};
struct bl808_boot_clk_cfg_t {
uint32_t magiccode;
struct bl808_sys_clk_cfg_t cfg;
uint32_t crc32;
};
struct bl808_boot_basic_cfg_t {
uint32_t sign_type : 2; /* [1: 0] for sign */
uint32_t encrypt_type : 2; /* [3: 2] for encrypt */
uint32_t key_sel : 2; /* [5: 4] key slot */
uint32_t xts_mode : 1; /* [6] for xts mode */
uint32_t aes_region_lock : 1; /* [7] rsvd */
uint32_t no_segment : 1; /* [8] no segment info */
uint32_t rsvd_0 : 1; /* [9] boot2 enable(rsvd_0) */
uint32_t rsvd_1 : 1; /* [10] boot2 rollback(rsvd_1) */
uint32_t cpu_master_id : 4; /* [14: 11] master id */
uint32_t notload_in_bootrom : 1; /* [15] notload in bootrom */
uint32_t crc_ignore : 1; /* [16] ignore crc */
uint32_t hash_ignore : 1; /* [17] hash ignore */
uint32_t power_on_mm : 1; /* [18] power on mm */
uint32_t em_sel : 3; /* [21: 19] em_sel */
uint32_t cmds_en : 1; /* [22] command spliter enable */
uint32_t cmds_wrap_mode : 2; /* [24: 23] cmds wrap mode */
uint32_t cmds_wrap_len : 4; /* [28: 25] cmds wrap len */
uint32_t icache_invalid : 1; /* [29] icache invalid */
uint32_t dcache_invalid : 1; /* [30] dcache invalid */
uint32_t rsvd_3 : 1; /* [31] rsvd_3 */
uint32_t group_image_offset; /* flash controller offset */
uint32_t aes_region_len; /* aes region length */
uint32_t img_len_cnt; /* image length or segment count */
uint32_t hash[32 / 4]; /* hash of the image */
};
struct bl808_boot_cpu_cfg_t {
uint8_t config_enable; /* coinfig this cpu */
uint8_t halt_cpu; /* halt this cpu */
uint8_t cache_enable : 1; /* cache setting */
uint8_t cache_wa : 1; /* cache setting */
uint8_t cache_wb : 1; /* cache setting */
uint8_t cache_wt : 1; /* cache setting */
uint8_t cache_way_dis : 4; /* cache setting */
uint8_t rsvd;
uint32_t cache_range_h; /* cache range high */
uint32_t cache_range_l; /* cache range low */
uint32_t image_address_offset; /* image_address_offset */
uint32_t rsvd0; /* rsvd0 */
uint32_t msp_val; /* msp value */
};
struct bl808_aesiv_cfg_t {
uint8_t aesiv[16];
uint32_t crc32;
};
struct bl808_pkey_cfg_t {
uint8_t eckeyx[32]; /* ec key in boot header */
uint8_t eckeyy[32]; /* ec key in boot header */
uint32_t crc32;
};
struct bl808_sign_cfg_t {
uint32_t sig_len;
uint8_t signature[32];
uint32_t crc32;
};
struct bl808_bootheader_t {
uint32_t magiccode; /* 4 */
uint32_t rivison; /* 4 */
struct bl808_boot_flash_cfg_t flash_cfg; /* 4 + 84 + 4 */
struct bl808_boot_clk_cfg_t clk_cfg; /* 4 + 20 + 4 */
struct bl808_boot_basic_cfg_t basic_cfg; /* 4 + 4 + 4 + 4 + 4*8 */
struct bl808_boot_cpu_cfg_t cpu_cfg[3]; /*24*3 */
uint32_t boot2_pt_table_0_rsvd; /* address of partition table 0 */ /* 4 */
uint32_t boot2_pt_table_1_rsvd; /* address of partition table 1 */ /* 4 */
uint32_t flash_cfg_table_addr; /* address of flashcfg table list */ /* 4 */
uint32_t flash_cfg_table_len; /* flashcfg table list len */ /* 4 */
uint32_t rsvd0[8]; /* rsvd */
uint32_t rsvd1[8]; /* rsvd */
uint32_t rsvd3[5]; /* 20 */
uint32_t crc32; /* 4 */
};
static_assert(sizeof(struct bl808_bootheader_t) == 352,
"BL808 bootheader size mismatch");
#pragma pack(pop)
#endif
+39 -9
View File
@@ -2,20 +2,35 @@
#ifndef _BLISP_UTIL_H
#define _BLISP_UTIL_H
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#ifdef WIN32
# include <windows.h>
#include <windows.h>
#else
# include <time.h>
#include <time.h>
#endif
void blisp_dlog(const char* format, ...);
static void blisp_dlog(const char* format, ...)
{
fflush(stdout);
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fputc('\n', stderr);
}
void blisp_dlog_no_nl(const char* format, ...);
void sleep_ms(int milliseconds);
uint32_t crc32_calculate(const void *data, size_t data_len);
static void sleep_ms(int milliseconds) {
#ifdef WIN32
Sleep(milliseconds);
#else
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(&ts, NULL);
#endif
}
/**
* * Generated on Mon Jan 9 19:56:36 2023
@@ -65,4 +80,19 @@ static const uint32_t crc_table[256] = {
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
#endif
static uint32_t crc32_calculate(const void *data, size_t data_len)
{
uint32_t crc = 0xffffffff;
const unsigned char *d = (const unsigned char *)data;
unsigned int tbl_idx;
while (data_len--) {
tbl_idx = (crc ^ *d) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
d++;
}
return (crc & 0xffffffff) ^ 0xffffffff;
}
#endif
+20 -212
View File
@@ -11,15 +11,11 @@
#include <sys/ioctl.h>
#endif
#include <blisp_struct.h>
#define DEBUG
static void drain(struct sp_port* port) {
#if defined(__APPLE__) || defined(__FreeBSD__)
sp_drain(port);
#else
(void)port; // unused
#endif
}
@@ -27,24 +23,12 @@ blisp_return_t blisp_device_init(struct blisp_device* device,
struct blisp_chip* chip) {
device->chip = chip;
device->is_usb = false;
fill_crcs(&bl808_header);
if (device->chip->type == BLISP_CHIP_BL808) {
// TODO: For some reason the BL808 does not send pending ('PD') responses
// during long (i.e. erase) operations, so we must disable response
// timeouts. Further investigation is necessary.
device->serial_timeout = 0;
} else {
device->serial_timeout = 1000;
}
return BLISP_OK;
}
blisp_return_t blisp_device_open(struct blisp_device* device,
const char* port_name,
uint32_t baudrate) {
enum sp_return ret;
const char* port_name) {
blisp_return_t ret;
struct sp_port* serial_port = NULL;
if (port_name != NULL) {
@@ -98,7 +82,11 @@ blisp_return_t blisp_device_open(struct blisp_device* device,
int vid, pid;
sp_get_port_usb_vid_pid(serial_port, &vid, &pid);
device->is_usb = pid == 0xFFFF;
device->current_baud_rate = baudrate;
// if (device->is_usb) {
// device->current_baud_rate = 2000000;
// } else {
device->current_baud_rate = 460800;
// }
#if 0
int fd;
@@ -157,9 +145,8 @@ blisp_return_t blisp_receive_response(struct blisp_device* device,
bool expect_payload) {
// TODO: Check checksum
int ret;
struct sp_port* serial_port = device->serial_port;
ret = sp_blocking_read(serial_port, &device->rx_buffer[0], 2, device->serial_timeout);
ret = sp_blocking_read(serial_port, &device->rx_buffer[0], 2, 1000);
if (ret < 2) {
blisp_dlog("Failed to receive response, ret: %d", ret);
return BLISP_ERR_NO_RESPONSE;
@@ -190,7 +177,6 @@ blisp_return_t blisp_receive_response(struct blisp_device* device,
blisp_return_t blisp_device_handshake(struct blisp_device* device,
bool in_ef_loader) {
int ret;
bool ok = false;
uint8_t handshake_buffer[600];
struct sp_port* serial_port = device->serial_port;
@@ -204,8 +190,8 @@ blisp_return_t blisp_device_handshake(struct blisp_device* device,
sleep_ms(50); // Wait a bit so BootROM can init
}
uint32_t bytes_count = (uint32_t)(device->chip->handshake_byte_multiplier *
(float)device->current_baud_rate / 10.0f);
uint32_t bytes_count = device->chip->handshake_byte_multiplier *
(float)device->current_baud_rate / 10.0f;
if (bytes_count > 600)
bytes_count = 600;
memset(handshake_buffer, 'U', bytes_count);
@@ -230,40 +216,14 @@ blisp_return_t blisp_device_handshake(struct blisp_device* device,
sp_flush(serial_port, SP_BUF_INPUT); // Flush garbage out of RX
}
if (device->chip->type == BLISP_CHIP_BL808) {
sleep_ms(300);
static const uint8_t second_handshake[] = { 0x50, 0x00, 0x08, 0x00, 0x38, 0xF0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18 };
ret = sp_blocking_write(serial_port, second_handshake, sizeof(second_handshake), 300);
if (ret < 0) {
blisp_dlog("Second handshake write failed, ret %d", ret);
return BLISP_ERR_API_ERROR;
}
}
ret = sp_blocking_read(serial_port, device->rx_buffer, 20, 50);
ret = sp_blocking_read(serial_port, device->rx_buffer, 2, 50);
if (ret >= 2) {
for (uint8_t j = 0; j < (ret - 1); j++) {
if (device->rx_buffer[j] == 'O' && device->rx_buffer[j + 1] == 'K') {
ok = true;
}
if (device->rx_buffer[0] == 'O' && device->rx_buffer[1] == 'K') {
return BLISP_OK;
}
}
if (ok) {
return BLISP_OK;
} else {
blisp_dlog("Received incorrect handshake response from chip (attempt %d/5).", i+1);
blisp_dlog_no_nl("Could not find 0x%02X 0x%02X ('O', 'K') in: ", 'O', 'K');
if (ret) {
for (uint8_t j=0; j <= ret; j++) {
blisp_dlog_no_nl("0x%02X ", device->rx_buffer[j]);
}
}
blisp_dlog("");
}
}
blisp_dlog("Did not receive correct response from chip after 5 attempts.");
blisp_dlog("Received no response from chip.");
return BLISP_ERR_NO_RESPONSE;
}
@@ -279,15 +239,13 @@ blisp_return_t blisp_device_get_boot_info(struct blisp_device* device,
if (ret < 0)
return ret;
// TODO: Endianess; this may break on big endian machines
memcpy(boot_info->boot_rom_version, &device->rx_buffer[0], 4);
memcpy(boot_info->boot_rom_version, &device->rx_buffer[0],
4); // TODO: Endianess; this may break on big endian machines
if (device->chip->type == BLISP_CHIP_BL70X) {
memcpy(boot_info->chip_id, &device->rx_buffer[16], 8);
} else {
memcpy(boot_info->chip_id, &device->rx_buffer[12], 6);
}
// TODO: BL60X
return BLISP_OK;
}
@@ -402,24 +360,13 @@ blisp_return_t blisp_device_flash_erase(struct blisp_device* device,
*(uint32_t*)(payload + 4) = end_address;
blisp_return_t ret = blisp_send_command(device, 0x30, payload, 8, true);
if (ret != BLISP_OK)
if (ret < 0)
return ret;
do {
ret = blisp_receive_response(device, false);
} while (ret == BLISP_ERR_PENDING);
return ret;
}
blisp_return_t blisp_device_chip_erase(struct blisp_device* device) {
blisp_return_t ret = blisp_send_command(device, 0x3C, NULL, 0, true);
if (ret != BLISP_OK)
return ret;
do {
ret = blisp_receive_response(device, false);
} while (ret == BLISP_ERR_PENDING);
return ret;
return 0;
}
blisp_return_t blisp_device_flash_write(struct blisp_device* device,
@@ -467,143 +414,4 @@ blisp_return_t blisp_device_reset(struct blisp_device* device) {
void blisp_device_close(struct blisp_device* device) {
struct sp_port* serial_port = device->serial_port;
sp_close(serial_port);
}
blisp_return_t bl808_load_clock_para(struct blisp_device* device,
bool irq_en, uint32_t baudrate) {
#define bl808_load_clock_para_payload_size 36
static_assert(bl808_load_clock_para_payload_size == sizeof(struct bl808_boot_clk_cfg_t) + 8,
"BL808 clock parameter struct size mismatch");
uint8_t payload[bl808_load_clock_para_payload_size] = { 0 };
uint32_t irq_enable = irq_en ? 1 : 0;
memcpy(&payload[0], &irq_enable, 4);
memcpy(&payload[4], &baudrate, 4);
memcpy(&payload[8], &bl808_header.clk_cfg, sizeof(struct bl808_boot_clk_cfg_t));
blisp_return_t ret = blisp_send_command(device, 0x22, payload,
bl808_load_clock_para_payload_size, true);
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0)
return ret;
return BLISP_OK;
}
blisp_return_t bl808_load_flash_para(struct blisp_device* device) {
// TODO: I don't understand why these parameters are the way they are,
// but at least they are labeled. Also, flash_io_mode and flash_clk_delay
// seem to be duplicated in the main spi_flash_cfg_t struct?
const uint8_t flash_pin = 0x4;
const uint8_t flash_clk_cfg = 0x41;
const uint8_t flash_io_mode = 0x01;
const uint8_t flash_clk_delay = 0;
// Yes, these values are (slightly) different to the ones in blisp_chip_bl808.c
// These values were obtained by observing the raw bytes sent by Bouffalo's
// own flashing software. So for whatever reason, the flash configuration needs
// to be different when flashing the chip vs. when the chip is running normally.
static const struct bl808_spi_flash_cfg_t cfg = {
.ioMode = 0x04,
.cReadSupport = 0x01,
.clkDelay = 0,
.clkInvert = 0,
.resetEnCmd = 0x66,
.resetCmd = 0x99,
.resetCreadCmd = 0xff,
.resetCreadCmdSize = 0x03,
.jedecIdCmd = 0x9f,
.jedecIdCmdDmyClk = 0,
.enter32BitsAddrCmd = 0xb7,
.exit32BitsAddrCmd = 0xe9,
.sectorSize = 0x04,
.mid = 0xef,
.pageSize = 0x100,
.chipEraseCmd = 0xc7,
.sectorEraseCmd = 0x20,
.blk32EraseCmd = 0x52,
.blk64EraseCmd = 0xd8,
.writeEnableCmd = 0x06,
.pageProgramCmd = 0x02,
.qpageProgramCmd = 0x32,
.qppAddrMode = 0,
.fastReadCmd = 0x0b,
.frDmyClk = 0x01,
.qpiFastReadCmd = 0x0b,
.qpiFrDmyClk = 0x01,
.fastReadDoCmd = 0x3b,
.frDoDmyClk = 0x01,
.fastReadDioCmd = 0xbb,
.frDioDmyClk = 0,
.fastReadQoCmd = 0x6b,
.frQoDmyClk = 0x01,
.fastReadQioCmd = 0xeb,
.frQioDmyClk = 0x02,
.qpiFastReadQioCmd = 0xeb,
.qpiFrQioDmyClk = 0x02,
.qpiPageProgramCmd = 0x02,
.writeVregEnableCmd = 0x50,
.wrEnableIndex = 0,
.qeIndex = 0x01,
.busyIndex = 0,
.wrEnableBit = 0x01,
.qeBit = 0x01,
.busyBit = 0,
.wrEnableWriteRegLen = 0x02,
.wrEnableReadRegLen = 0x01,
.qeWriteRegLen = 0x01,
.qeReadRegLen = 0x01,
.releasePowerDown = 0xab,
.busyReadRegLen = 0x01,
.readRegCmd[0] = 0x05,
.readRegCmd[1] = 0x35,
.readRegCmd[2] = 0,
.readRegCmd[3] = 0,
.writeRegCmd[0] = 0x01,
.writeRegCmd[1] = 0x31,
.writeRegCmd[2] = 0,
.writeRegCmd[3] = 0,
.enterQpi = 0x38,
.exitQpi = 0xff,
.cReadMode = 0xa0,
.cRExit = 0xff,
.burstWrapCmd = 0x77,
.burstWrapCmdDmyClk = 0x03,
.burstWrapDataMode = 0x02,
.burstWrapData = 0x40,
.deBurstWrapCmd = 0x77,
.deBurstWrapCmdDmyClk = 0x03,
.deBurstWrapDataMode = 0x02,
.deBurstWrapData = 0xf0,
.timeEsector = 0x12c,
.timeE32k = 0x4b0,
.timeE64k = 0x4b0,
.timePagePgm = 0x05,
.timeCe = 0x80e8,
.pdDelay = 0x03,
.qeData = 0,
};
#define bl808_load_flash_para_payload_size 88
static_assert(bl808_load_flash_para_payload_size == sizeof(struct bl808_spi_flash_cfg_t) + 4,
"BL808 flash parameter struct size mismatch");
uint8_t payload[bl808_load_flash_para_payload_size] = { 0 };
payload[0] = flash_pin;
payload[1] = flash_clk_cfg;
payload[2] = flash_io_mode;
payload[3] = flash_clk_delay;
memcpy(&payload[4], &cfg, sizeof(struct bl808_spi_flash_cfg_t));
blisp_return_t ret = blisp_send_command(device, 0x3b, payload,
bl808_load_flash_para_payload_size, true);
if (ret < 0)
return ret;
ret = blisp_receive_response(device, false);
if (ret < 0)
return ret;
return BLISP_OK;
}
}
-55
View File
@@ -1,55 +0,0 @@
// SPDX-License-Identifier: MIT
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#ifdef WIN32
# include <windows.h>
#else
# include <time.h>
#endif
#include "blisp_util.h"
void blisp_dlog(const char* format, ...)
{
fflush(stdout);
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fputc('\n', stderr);
}
void blisp_dlog_no_nl(const char* format, ...) {
fflush(stdout);
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
}
void sleep_ms(int milliseconds) {
#ifdef WIN32
Sleep(milliseconds);
#else
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(&ts, NULL);
#endif
}
uint32_t crc32_calculate(const void *data, size_t data_len)
{
uint32_t crc = 0xffffffff;
const unsigned char *d = (const unsigned char *)data;
unsigned int tbl_idx;
while (data_len--) {
tbl_idx = (crc ^ *d) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
d++;
}
return (crc & 0xffffffff) ^ 0xffffffff;
}
-2
View File
@@ -6,8 +6,6 @@
int64_t blisp_chip_bl60x_get_eflash_loader(uint8_t clk_type, uint8_t** firmware_buf_ptr)
{
(void)clk_type; // unused
uint8_t* firmware_buf = malloc(sizeof(bl60x_eflash_loader_bin));
memcpy(firmware_buf, bl60x_eflash_loader_bin, sizeof(bl60x_eflash_loader_bin));
*(firmware_buf + 0xE0) = 4; // TODO: 40 MHz clock
-2
View File
@@ -6,8 +6,6 @@
int64_t blisp_chip_bl70x_get_eflash_loader(uint8_t clk_type, uint8_t** firmware_buf_ptr)
{
(void) clk_type; // ununsed
uint8_t* firmware_buf = malloc(sizeof(bl70x_eflash_loader_bin));
memcpy(firmware_buf, bl70x_eflash_loader_bin, sizeof(bl70x_eflash_loader_bin));
*(firmware_buf + 0xE0) = 1; // TODO: 32 MHz clock
+4 -224
View File
@@ -1,231 +1,11 @@
/*
* Some parts of this source code belongs to Bouffalo Labs
* COPYRIGHT(c) 2020 Bouffalo Lab , License: Apache
*/
// SPDX-License-Identifier: MIT
#include "blisp.h"
#include "blisp_struct.h"
#include "blisp_util.h"
#include <stddef.h>
struct blisp_chip blisp_chip_bl808 = {
.type = BLISP_CHIP_BL808,
.type_str = "bl808",
.usb_isp_available = true, // TODO: Only for BL808D :-(
.default_xtal = "-", // XXX: bfl software marks this as "Auto (0x07)"
.handshake_byte_multiplier = 0.006f,
.load_eflash_loader = NULL
.default_xtal = "-", // ?
.handshake_byte_multiplier = 0.003f,
.get_eflash_loader = NULL
};
struct bl808_bootheader_t bl808_header = {
.magiccode = 0x504e4642,
.rivison = 0x00000001,
/*flash config */
.flash_cfg.magiccode = 0x47464346,
.flash_cfg.cfg.ioMode = 0x11, /*!< Serail flash interface mode,bit0-3:IF mode,bit4:unwrap */
.flash_cfg.cfg.cReadSupport = 0x00, /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */
.flash_cfg.cfg.clkDelay = 0x01, /*!< SPI clock delay,bit0-3:delay,bit4-6:pad delay */
.flash_cfg.cfg.clkInvert = 0x01, /*!< SPI clock phase invert,bit0:clck invert,bit1:rx invert,bit2-4:pad delay,bit5-7:pad delay */
.flash_cfg.cfg.resetEnCmd = 0x66, /*!< Flash enable reset command */
.flash_cfg.cfg.resetCmd = 0x99, /*!< Flash reset command */
.flash_cfg.cfg.resetCreadCmd = 0xff, /*!< Flash reset continuous read command */
.flash_cfg.cfg.resetCreadCmdSize = 0x03, /*!< Flash reset continuous read command size */
.flash_cfg.cfg.jedecIdCmd = 0x9f, /*!< JEDEC ID command */
.flash_cfg.cfg.jedecIdCmdDmyClk = 0x00, /*!< JEDEC ID command dummy clock */
.flash_cfg.cfg.enter32BitsAddrCmd = 0xb7, /*!< Enter 32-bits addr command */
.flash_cfg.cfg.exit32BitsAddrCmd = 0xe9, /*!< Exit 32-bits addr command */
.flash_cfg.cfg.sectorSize = 0x04, /*!< *1024bytes */
.flash_cfg.cfg.mid = 0x00, /*!< Manufacturer ID */
.flash_cfg.cfg.pageSize = 0x100, /*!< Page size */
.flash_cfg.cfg.chipEraseCmd = 0xc7, /*!< Chip erase cmd */
.flash_cfg.cfg.sectorEraseCmd = 0x20, /*!< Sector erase command */
.flash_cfg.cfg.blk32EraseCmd = 0x52, /*!< Block 32K erase command,some Micron not support */
.flash_cfg.cfg.blk64EraseCmd = 0xd8, /*!< Block 64K erase command */
.flash_cfg.cfg.writeEnableCmd = 0x06, /*!< Need before every erase or program */
.flash_cfg.cfg.pageProgramCmd = 0x02, /*!< Page program cmd */
.flash_cfg.cfg.qpageProgramCmd = 0x32, /*!< QIO page program cmd */
.flash_cfg.cfg.qppAddrMode = 0x00, /*!< QIO page program address mode */
.flash_cfg.cfg.fastReadCmd = 0x0b, /*!< Fast read command */
.flash_cfg.cfg.frDmyClk = 0x01, /*!< Fast read command dummy clock */
.flash_cfg.cfg.qpiFastReadCmd = 0x0b, /*!< QPI fast read command */
.flash_cfg.cfg.qpiFrDmyClk = 0x01, /*!< QPI fast read command dummy clock */
.flash_cfg.cfg.fastReadDoCmd = 0x3b, /*!< Fast read dual output command */
.flash_cfg.cfg.frDoDmyClk = 0x01, /*!< Fast read dual output command dummy clock */
.flash_cfg.cfg.fastReadDioCmd = 0xbb, /*!< Fast read dual io comamnd */
.flash_cfg.cfg.frDioDmyClk = 0x00, /*!< Fast read dual io command dummy clock */
.flash_cfg.cfg.fastReadQoCmd = 0x6b, /*!< Fast read quad output comamnd */
.flash_cfg.cfg.frQoDmyClk = 0x01, /*!< Fast read quad output comamnd dummy clock */
.flash_cfg.cfg.fastReadQioCmd = 0xeb, /*!< Fast read quad io comamnd */
.flash_cfg.cfg.frQioDmyClk = 0x02, /*!< Fast read quad io comamnd dummy clock */
.flash_cfg.cfg.qpiFastReadQioCmd = 0xeb, /*!< QPI fast read quad io comamnd */
.flash_cfg.cfg.qpiFrQioDmyClk = 0x02, /*!< QPI fast read QIO dummy clock */
.flash_cfg.cfg.qpiPageProgramCmd = 0x02, /*!< QPI program command */
.flash_cfg.cfg.writeVregEnableCmd = 0x50, /*!< Enable write reg */
.flash_cfg.cfg.wrEnableIndex = 0x00, /*!< Write enable register index */
.flash_cfg.cfg.qeIndex = 0x01, /*!< Quad mode enable register index */
.flash_cfg.cfg.busyIndex = 0x00, /*!< Busy status register index */
.flash_cfg.cfg.wrEnableBit = 0x01, /*!< Write enable bit pos */
.flash_cfg.cfg.qeBit = 0x01, /*!< Quad enable bit pos */
.flash_cfg.cfg.busyBit = 0x00, /*!< Busy status bit pos */
.flash_cfg.cfg.wrEnableWriteRegLen = 0x02, /*!< Register length of write enable */
.flash_cfg.cfg.wrEnableReadRegLen = 0x01, /*!< Register length of write enable status */
.flash_cfg.cfg.qeWriteRegLen = 0x02, /*!< Register length of contain quad enable */
.flash_cfg.cfg.qeReadRegLen = 0x01, /*!< Register length of contain quad enable status */
.flash_cfg.cfg.releasePowerDown = 0xab, /*!< Release power down command */
.flash_cfg.cfg.busyReadRegLen = 0x01, /*!< Register length of contain busy status */
.flash_cfg.cfg.readRegCmd[0] = 0x05, /*!< Read register command buffer */
.flash_cfg.cfg.readRegCmd[1] = 0x35, /*!< Read register command buffer */
.flash_cfg.cfg.readRegCmd[2] = 0x00, /*!< Read register command buffer */
.flash_cfg.cfg.readRegCmd[3] = 0x00, /*!< Read register command buffer */
.flash_cfg.cfg.writeRegCmd[0] = 0x01, /*!< Write register command buffer */
.flash_cfg.cfg.writeRegCmd[1] = 0x01, /*!< Write register command buffer */
.flash_cfg.cfg.writeRegCmd[2] = 0x00, /*!< Write register command buffer */
.flash_cfg.cfg.writeRegCmd[3] = 0x00, /*!< Write register command buffer */
.flash_cfg.cfg.enterQpi = 0x38, /*!< Enter qpi command */
.flash_cfg.cfg.exitQpi = 0xff, /*!< Exit qpi command */
.flash_cfg.cfg.cReadMode = 0x20, /*!< Config data for continuous read mode */
.flash_cfg.cfg.cRExit = 0xf0, /*!< Config data for exit continuous read mode */
.flash_cfg.cfg.burstWrapCmd = 0x77, /*!< Enable burst wrap command */
.flash_cfg.cfg.burstWrapCmdDmyClk = 0x03, /*!< Enable burst wrap command dummy clock */
.flash_cfg.cfg.burstWrapDataMode = 0x02, /*!< Data and address mode for this command */
.flash_cfg.cfg.burstWrapData = 0x40, /*!< Data to enable burst wrap */
.flash_cfg.cfg.deBurstWrapCmd = 0x77, /*!< Disable burst wrap command */
.flash_cfg.cfg.deBurstWrapCmdDmyClk = 0x03, /*!< Disable burst wrap command dummy clock */
.flash_cfg.cfg.deBurstWrapDataMode = 0x02, /*!< Data and address mode for this command */
.flash_cfg.cfg.deBurstWrapData = 0xf0, /*!< Data to disable burst wrap */
.flash_cfg.cfg.timeEsector = 300, /*!< 4K erase time */
.flash_cfg.cfg.timeE32k = 1200, /*!< 32K erase time */
.flash_cfg.cfg.timeE64k = 1200, /*!< 64K erase time */
.flash_cfg.cfg.timePagePgm = 50, /*!< Page program time */
.flash_cfg.cfg.timeCe = 30000, /*!< Chip erase time in ms */
.flash_cfg.cfg.pdDelay = 20, /*!< Release power down command delay time for wake up */
.flash_cfg.cfg.qeData = 0, /*!< QE set data */
.flash_cfg.crc32 = 0xdeadbeef,
/* clock cfg */
.clk_cfg.magiccode = 0x47464350,
.clk_cfg.cfg.xtal_type = 0x07, /*!< 0:None,1:24M,2:32M,3:38.4M,4:40M,5:26M,6:RC32M */
.clk_cfg.cfg.mcu_clk = 0x04, /*!< mcu_clk 0:RC32M,1:Xtal,2:cpupll 400M,3:wifipll 192M,4:wifipll 320M */
.clk_cfg.cfg.mcu_clk_div = 0x00,
.clk_cfg.cfg.mcu_bclk_div = 0x00,
.clk_cfg.cfg.mcu_pbclk_div = 0x03,
.clk_cfg.cfg.lp_div = 0x01,
.clk_cfg.cfg.dsp_clk = 0x03, /* 0:RC32M,1:Xtal,2:wifipll 240M,3:wifipll 320M,4:cpupll 400M */
.clk_cfg.cfg.dsp_clk_div = 0x00,
.clk_cfg.cfg.dsp_bclk_div = 0x01,
.clk_cfg.cfg.dsp_pbclk = 0x02, /* 0:RC32M,1:Xtal,2:wifipll 160M,3:cpupll 160M,4:wifipll 240M */
.clk_cfg.cfg.dsp_pbclk_div = 0x00,
.clk_cfg.cfg.emi_clk = 0x02, /*!< 0:mcu pbclk,1:cpupll 200M,2:wifipll 320M,3:cpupll 400M */
.clk_cfg.cfg.emi_clk_div = 0x01,
.clk_cfg.cfg.flash_clk_type = 0x01, /*!< 0:wifipll 120M,1:xtal,2:cpupll 100M,3:wifipll 80M,4:bclk,5:wifipll 96M */
.clk_cfg.cfg.flash_clk_div = 0x00,
.clk_cfg.cfg.wifipll_pu = 0x01,
.clk_cfg.cfg.aupll_pu = 0x01,
.clk_cfg.cfg.cpupll_pu = 0x01,
.clk_cfg.cfg.mipipll_pu = 0x01,
.clk_cfg.cfg.uhspll_pu = 0x01,
.clk_cfg.crc32 = 0xdeadbeef,
/* basic cfg */
.basic_cfg.sign_type = 0x0, /* [1: 0] for sign */
.basic_cfg.encrypt_type = 0x0, /* [3: 2] for encrypt */
.basic_cfg.key_sel = 0x0, /* [5: 4] key slot */
.basic_cfg.xts_mode = 0x0, /* [6] for xts mode */
.basic_cfg.aes_region_lock = 0x0, /* [7] rsvd */
.basic_cfg.no_segment = 0x1, /* [8] no segment info */
.basic_cfg.rsvd_0 = 0x0, /* [9] boot2 enable(rsvd_0) */
.basic_cfg.rsvd_1 = 0x0, /* [10] boot2 rollback(rsvd_1) */
.basic_cfg.cpu_master_id = 0x0, /* [14: 11] master id */
.basic_cfg.notload_in_bootrom = 0x0, /* [15] notload in bootrom */
.basic_cfg.crc_ignore = 0x1, /* [16] ignore crc */
.basic_cfg.hash_ignore = 0x1, /* [17] hash ignore */
.basic_cfg.power_on_mm = 0x1, /* [18] power on mm */
.basic_cfg.em_sel = 0x1, /* [21: 19] em_sel */
.basic_cfg.cmds_en = 0x1, /* [22] command spliter enable */
#if 0
# 0 : cmds bypass wrap commands to macro, original mode;
# 1 : cmds handle wrap commands, original mode;
# 2 : cmds bypass wrap commands to macro, cmds force wrap16 * 4 splitted into two wrap8 * 4;
# 3 : cmds handle wrap commands, cmds force wrap16 * 4 splitted into two wrap8 * 4
#endif
.basic_cfg.cmds_wrap_mode = 0x1, /* [24: 23] cmds wrap mode */
#if 0
# 0 : SF_CTRL_WRAP_LEN_8, 1 : SF_CTRL_WRAP_LEN_16, 2 : SF_CTRL_WRAP_LEN_32,
# 3 : SF_CTRL_WRAP_LEN_64, 9 : SF_CTRL_WRAP_LEN_4096
#endif
.basic_cfg.cmds_wrap_len = 0x9, /* [28: 25] cmds wrap len */
.basic_cfg.icache_invalid = 0x1, /* [29] icache invalid */
.basic_cfg.dcache_invalid = 0x1, /* [30] dcache invalid */
.basic_cfg.rsvd_3 = 0x0, /* [31] rsvd_3 */
#ifdef BFLB_BOOT2
.basic_cfg.group_image_offset = 0x00002000, /* flash controller offset */
#else
.basic_cfg.group_image_offset = 0x00001000, /* flash controller offset */
#endif
.basic_cfg.aes_region_len = 0x00000000, /* aes region length */
.basic_cfg.img_len_cnt = 0x00010000, /* image length or segment count */
.basic_cfg.hash = { 0xdeadbeef }, /* hash of the image */
/* cpu cfg */
.cpu_cfg[0].config_enable = 0x01, /* coinfig this cpu */
.cpu_cfg[0].halt_cpu = 0x0, /* halt this cpu */
.cpu_cfg[0].cache_enable = 0x0, /* cache setting :only for BL Cache */
.cpu_cfg[0].cache_wa = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[0].cache_wb = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[0].cache_wt = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[0].cache_way_dis = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[0].rsvd = 0x0,
.cpu_cfg[0].cache_range_h = 0x00000000,
.cpu_cfg[0].cache_range_l = 0x00000000,
/* image_address_offset */
.cpu_cfg[0].image_address_offset = 0x0,
.cpu_cfg[0].rsvd0 = 0x58000000, /* rsvd0 */
.cpu_cfg[0].msp_val = 0x00000000, /* msp value */
/* cpu cfg */
.cpu_cfg[1].config_enable = 0x0, /* coinfig this cpu */
.cpu_cfg[1].halt_cpu = 0x0, /* halt this cpu */
.cpu_cfg[1].cache_enable = 0x0, /* cache setting :only for BL Cache */
.cpu_cfg[1].cache_wa = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[1].cache_wb = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[1].cache_wt = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[1].cache_way_dis = 0x0, /* cache setting :only for BL Cache*/
.cpu_cfg[1].rsvd = 0x0,
.cpu_cfg[1].cache_range_h = 0x00000000,
.cpu_cfg[1].cache_range_l = 0x00000000,
/* image_address_offset */
.cpu_cfg[1].image_address_offset = 0x0,
.cpu_cfg[1].rsvd0 = 0x58000000, /* rsvd0 */
.cpu_cfg[1].msp_val = 0x00000000, /* msp value */
/* address of partition table 0 */ /* 4 */
.boot2_pt_table_0_rsvd = 0x00000000,
/* address of partition table 1 */ /* 4 */
.boot2_pt_table_1_rsvd = 0x00000000,
/* address of flashcfg table list */ /* 4 */
.flash_cfg_table_addr = 0x00000000,
/* flashcfg table list len */ /* 4 */
.flash_cfg_table_len = 0x00000000,
.rsvd1[0] = 0x20000320,
.rsvd1[1] = 0x00000000,
.rsvd1[2] = 0x2000F038,
.rsvd1[3] = 0x18000000,
.crc32 = 0xdeadbeef /* 4 */
};
void fill_crcs(struct bl808_bootheader_t *bh) {
bh->flash_cfg.crc32 = crc32_calculate((unsigned char *) &bh->flash_cfg.cfg, sizeof(struct bl808_spi_flash_cfg_t));
bh->clk_cfg.crc32 = crc32_calculate((unsigned char *) &bh->clk_cfg.cfg, sizeof(struct bl808_sys_clk_cfg_t));
bh->crc32 = crc32_calculate((unsigned char *) bh, sizeof(struct bl808_bootheader_t) - 4);
}
-10
View File
@@ -23,16 +23,6 @@ target_link_libraries(blisp PRIVATE
argtable3::argtable3
libblisp_static file_parsers)
if (NOT CMAKE_C_COMPILER_ID MATCHES "MSVC")
target_compile_options(libblisp_obj PRIVATE -Wall -Wextra -Wpedantic)
else()
# MSVC does not support 'extra' and 'pedantic' levels to warnings.
# `/Wall` seems to generate way too many non-actionable output marked as warnings.
# We settle for `/W4`.
# https://learn.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level?view=msvc-170
target_compile_options(libblisp_obj PRIVATE -W4)
endif()
if (WIN32)
target_link_libraries(blisp PRIVATE Setupapi.lib)
elseif (APPLE)
+22 -54
View File
@@ -1,6 +1,5 @@
#include <argtable3.h>
#include <blisp_easy.h>
#include "../cmd.h"
#include "../common.h"
@@ -11,27 +10,15 @@ static struct arg_rex* cmd;
static struct arg_file* single_download;
static struct arg_int* single_download_location;
static struct arg_str *port_name, *chip_type; // TODO: Make this common
static struct arg_int *baudrate;
static struct arg_lit* reset;
static struct arg_lit* chiperase;
static struct arg_end* end;
static void* cmd_iot_argtable[9];
static void* cmd_iot_argtable[7];
static void cmd_iot_args_print_glossary();
blisp_return_t blisp_single_download(void) {
blisp_return_t blisp_single_download() {
struct blisp_device device;
blisp_return_t ret;
uint32_t baud = DEFAULT_BAUDRATE;
if (baudrate->count == 1) {
if (*baudrate->ival < 0) {
fprintf(stderr, "Baud rate cannot be negative!\n");
return BLISP_ERR_INVALID_COMMAND;
} else {
baud = *baudrate->ival;
}
}
if (access(single_download->filename[0], R_OK) != 0) {
// File not accessible, error out.
fprintf(stderr, "Input firmware not found: %s\n", single_download->filename[0]);
@@ -40,25 +27,13 @@ blisp_return_t blisp_single_download(void) {
return 1;
}
ret = blisp_common_init_device(&device, port_name, chip_type, baud);
ret = blisp_common_init_device(&device, port_name, chip_type);
if (ret != BLISP_OK) {
return ret;
}
ret = blisp_common_prepare_flash(&device);
if (ret != BLISP_OK) {
// TODO: user-friendly error messages
fprintf(stderr, "Failed to initialize device, ret: %d\n", ret);
goto exit1;
}
if (chiperase->count) {
printf("Performing a chip erase, this might take a while...\n");
ret = blisp_device_chip_erase(&device);
if (ret == BLISP_OK) {
printf("Erase complete!\n");
} else {
fprintf(stderr, "Failed to erase, ret: %d\n", ret);
}
// TODO: Error handling
goto exit1;
}
@@ -76,9 +51,9 @@ blisp_return_t blisp_single_download(void) {
printf("Erasing the area, this might take a while...\n");
ret = blisp_device_flash_erase(
&device, *single_download_location->ival,
*single_download_location->ival + data_file_size - 1);
*single_download_location->ival + data_file_size + 1);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to erase, ret: %d\n", ret);
fprintf(stderr, "Failed to erase.\n");
goto exit2;
}
@@ -89,15 +64,15 @@ blisp_return_t blisp_single_download(void) {
ret = blisp_easy_flash_write(&device, &data_transport,
*single_download_location->ival, data_file_size,
blisp_common_progress_callback);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to write data to flash, ret: %d\n", ret);
if (ret < BLISP_OK) {
fprintf(stderr, "Failed to write data to flash.\n");
goto exit2;
}
printf("Checking program...\n");
ret = blisp_device_program_check(&device);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to check program, ret: %d\n", ret);
fprintf(stderr, "Failed to check program.\n");
goto exit2;
}
printf("Program OK!\n");
@@ -106,7 +81,7 @@ blisp_return_t blisp_single_download(void) {
printf("Resetting the chip.\n");
ret = blisp_device_reset(&device);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to reset chip, ret: %d\n", ret);
fprintf(stderr, "Failed to reset chip.\n");
goto exit2;
}
}
@@ -123,28 +98,21 @@ exit1:
return ret;
}
blisp_return_t cmd_iot_args_init(void) {
size_t index = 0;
cmd_iot_argtable[index++] = cmd =
blisp_return_t cmd_iot_args_init() {
cmd_iot_argtable[0] = cmd =
arg_rex1(NULL, NULL, "iot", NULL, REG_ICASE, NULL);
cmd_iot_argtable[index++] = chip_type =
cmd_iot_argtable[1] = chip_type =
arg_str1("c", "chip", "<chip_type>", "Chip Type");
cmd_iot_argtable[index++] = port_name =
cmd_iot_argtable[2] = port_name =
arg_str0("p", "port", "<port_name>",
"Name/Path to the Serial Port (empty for search)");
cmd_iot_argtable[index++] = baudrate =
arg_int0("b", "baudrate", "<baud rate>",
"Serial baud rate (default: " XSTR(DEFAULT_BAUDRATE) ")");
cmd_iot_argtable[index++] = reset =
cmd_iot_argtable[3] = reset =
arg_lit0(NULL, "reset", "Reset chip after write");
cmd_iot_argtable[index++] = chiperase =
arg_lit0(NULL, "chiperase", "Do not write any data; erase the entire chip instead");
cmd_iot_argtable[index++] = single_download =
cmd_iot_argtable[4] = single_download =
arg_file0("s", "single-down", "<file>", "Single download file");
cmd_iot_argtable[index++] = single_download_location =
cmd_iot_argtable[5] = single_download_location =
arg_int0("l", "single-down-loc", NULL, "Single download offset");
cmd_iot_argtable[index++] = end = arg_end(10);
cmd_iot_argtable[6] = end = arg_end(10);
if (arg_nullcheck(cmd_iot_argtable) != 0) {
fprintf(stderr, "insufficient memory\n");
@@ -153,7 +121,7 @@ blisp_return_t cmd_iot_args_init(void) {
return BLISP_OK;
}
void cmd_iot_args_print_glossary(void) {
void cmd_iot_args_print_glossary() {
fputs("Usage: blisp", stdout);
arg_print_syntax(stdout, cmd_iot_argtable, "\n");
puts("Flashes firmware as Bouffalo's DevCube");
@@ -163,7 +131,7 @@ void cmd_iot_args_print_glossary(void) {
blisp_return_t cmd_iot_parse_exec(int argc, char** argv) {
int errors = arg_parse(argc, argv, cmd_iot_argtable);
if (errors == 0) {
if (chiperase->count || (single_download->count == 1 && single_download_location->count == 1)) {
if (single_download->count == 1 && single_download_location->count == 1) {
return blisp_single_download();
} else {
return BLISP_ERR_INVALID_COMMAND;
@@ -175,11 +143,11 @@ blisp_return_t cmd_iot_parse_exec(int argc, char** argv) {
return BLISP_ERR_INVALID_COMMAND;
}
void cmd_iot_args_print_syntax(void) {
void cmd_iot_args_print_syntax() {
arg_print_syntax(stdout, cmd_iot_argtable, "\n");
}
void cmd_iot_free(void) {
void cmd_iot_free() {
arg_freetable(cmd_iot_argtable,
sizeof(cmd_iot_argtable) / sizeof(cmd_iot_argtable[0]));
}
+23 -45
View File
@@ -17,10 +17,9 @@
static struct arg_rex* cmd;
static struct arg_file* binary_to_write;
static struct arg_str *port_name, *chip_type;
static struct arg_int *baudrate;
static struct arg_lit* reset;
static struct arg_end* end;
static void* cmd_write_argtable[7];
static void* cmd_write_argtable[6];
static void cmd_write_args_print_glossary();
void fill_up_boot_header(struct bfl_boot_header* boot_header) {
@@ -167,47 +166,33 @@ void fill_up_boot_header(struct bfl_boot_header* boot_header) {
boot_header->crc32 = 0xDEADBEEF;
}
blisp_return_t blisp_flash_firmware(void) {
blisp_return_t blisp_flash_firmware() {
struct blisp_device device;
blisp_return_t ret = BLISP_OK;
uint32_t baud = DEFAULT_BAUDRATE;
if (baudrate->count == 1) {
if (*baudrate->ival < 0) {
fprintf(stderr, "Baud rate cannot be negative!\n");
return BLISP_ERR_INVALID_COMMAND;
} else {
baud = *baudrate->ival;
}
}
blisp_return_t ret;
if (access(binary_to_write->filename[0], R_OK) != 0) {
// File not accessible, error out.
fprintf(stderr, "Input firmware not found: %s\n", binary_to_write->filename[0]);
cmd_write_args_print_glossary(); /* Print help to assist user */
/* No need to free memory, will now exit with ret code 1 */
return BLISP_ERR_CANT_OPEN_FILE;
return 1;
}
ret = blisp_common_init_device(&device, port_name, chip_type, baud);
if (ret != BLISP_OK) {
ret = blisp_common_init_device(&device, port_name, chip_type);
if (ret != 0) {
return ret;
}
ret = blisp_common_prepare_flash(&device);
if (ret != BLISP_OK) {
if (blisp_common_prepare_flash(&device) != 0) {
// TODO: Error handling
goto exit1;
}
parsed_firmware_file_t parsed_file;
memset(&parsed_file, 0, sizeof(parsed_file));
if (parse_firmware_file(binary_to_write->filename[0], &parsed_file) < 0) {
// `parse_firmware_file` doesn't return `blisp_return_t`
// so we default to the generic error.
ret = BLISP_ERR_UNKNOWN;
goto exit1;
}
int parsed_result =
parse_firmware_file(binary_to_write->filename[0], &parsed_file);
// If we are injecting a bootloader section, make it, erase flash, and flash
// it. Then when we do firmware later on; it will be located afterwards
@@ -248,13 +233,13 @@ blisp_return_t blisp_flash_firmware(void) {
if (ret != BLISP_OK) {
fprintf(stderr,
"Failed to erase flash. Tried to erase from 0x%08zx to 0x%08zx\n",
"Failed to erase flash. Tried to erase from 0x%08lu to 0x%08lu\n",
parsed_file.payload_address,
parsed_file.payload_address + parsed_file.payload_length + 1);
goto exit2;
}
printf("Flashing the firmware %zu bytes @ 0x%08zx...\n",
printf("Flashing the firmware %lu bytes @ 0x%08lu...\n",
parsed_file.payload_length, parsed_file.payload_address);
struct blisp_easy_transport data_transport =
blisp_easy_transport_new_from_memory(parsed_file.payload,
@@ -264,7 +249,7 @@ blisp_return_t blisp_flash_firmware(void) {
&device, &data_transport, parsed_file.payload_address,
parsed_file.payload_length, blisp_common_progress_callback);
if (ret != BLISP_OK) {
if (ret < BLISP_OK) {
fprintf(stderr, "Failed to write app to flash.\n");
goto exit2;
}
@@ -290,28 +275,21 @@ exit2:
free(parsed_file.payload);
exit1:
blisp_device_close(&device);
return ret;
}
blisp_return_t cmd_write_args_init(void) {
size_t index = 0;
cmd_write_argtable[index++] = cmd =
blisp_return_t cmd_write_args_init() {
cmd_write_argtable[0] = cmd =
arg_rex1(NULL, NULL, "write", NULL, REG_ICASE, NULL);
cmd_write_argtable[index++] = chip_type =
cmd_write_argtable[1] = chip_type =
arg_str1("c", "chip", "<chip_type>", "Chip Type");
cmd_write_argtable[index++] = port_name =
cmd_write_argtable[2] = port_name =
arg_str0("p", "port", "<port_name>",
"Name/Path to the Serial Port (empty for search)");
cmd_write_argtable[index++] = baudrate =
arg_int0("b", "baudrate", "<baud rate>",
"Serial baud rate (default: " XSTR(DEFAULT_BAUDRATE) ")");
cmd_write_argtable[index++] = reset =
cmd_write_argtable[3] = reset =
arg_lit0(NULL, "reset", "Reset chip after write");
cmd_write_argtable[index++] = binary_to_write =
cmd_write_argtable[4] = binary_to_write =
arg_file1(NULL, NULL, "<input>", "Binary to write");
cmd_write_argtable[index++] = end = arg_end(10);
cmd_write_argtable[5] = end = arg_end(10);
if (arg_nullcheck(cmd_write_argtable) != 0) {
fprintf(stderr, "insufficient memory\n");
@@ -320,7 +298,7 @@ blisp_return_t cmd_write_args_init(void) {
return BLISP_OK;
}
void cmd_write_args_print_glossary(void) {
void cmd_write_args_print_glossary() {
fputs("Usage: blisp", stdout);
arg_print_syntax(stdout, cmd_write_argtable, "\n");
puts("Writes firmware to SPI Flash");
@@ -339,11 +317,11 @@ blisp_return_t cmd_write_parse_exec(int argc, char** argv) {
return BLISP_ERR_INVALID_COMMAND;
}
void cmd_write_args_print_syntax(void) {
void cmd_write_args_print_syntax() {
arg_print_syntax(stdout, cmd_write_argtable, "\n");
}
void cmd_write_free(void) {
void cmd_write_free() {
arg_freetable(cmd_write_argtable,
sizeof(cmd_write_argtable) / sizeof(cmd_write_argtable[0]));
}
+29 -85
View File
@@ -8,7 +8,6 @@
#include <stdlib.h>
#include <string.h>
#include "blisp_easy.h"
#include "blisp_util.h"
#include "error_codes.h"
#include "util.h"
@@ -20,8 +19,7 @@ void blisp_common_progress_callback(uint32_t current_value,
blisp_return_t blisp_common_init_device(struct blisp_device* device,
struct arg_str* port_name,
struct arg_str* chip_type,
uint32_t baudrate) {
struct arg_str* chip_type) {
if (chip_type->count == 0) {
fprintf(stderr, "Chip type is invalid.\n");
return BLISP_ERR_INVALID_CHIP_TYPE;
@@ -33,8 +31,6 @@ blisp_return_t blisp_common_init_device(struct blisp_device* device,
chip = &blisp_chip_bl70x;
} else if (strcmp(chip_type->sval[0], "bl60x") == 0) {
chip = &blisp_chip_bl60x;
} else if (strcmp(chip_type->sval[0], "bl808") == 0) {
chip = &blisp_chip_bl808;
} else {
fprintf(stderr, "Chip type is invalid.\n");
return BLISP_ERR_INVALID_CHIP_TYPE;
@@ -43,18 +39,15 @@ blisp_return_t blisp_common_init_device(struct blisp_device* device,
blisp_return_t ret;
ret = blisp_device_init(device, chip);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to init device, ret: %d\n", ret);
fprintf(stderr, "Failed to init device.\n");
return ret;
}
ret = blisp_device_open(device,
port_name->count == 1 ? port_name->sval[0] : NULL,
baudrate);
port_name->count == 1 ? port_name->sval[0] : NULL);
if (ret != BLISP_OK) {
if (ret == BLISP_ERR_DEVICE_NOT_FOUND) {
fprintf(stderr, "Device not found\n");
} else {
fprintf(stderr, "Failed to open device, ret: %d\n", ret);
}
fprintf(stderr, ret == BLISP_ERR_DEVICE_NOT_FOUND
? "Device not found\n"
: "Failed to open device.\n");
return ret;
}
@@ -67,78 +60,29 @@ blisp_return_t blisp_common_init_device(struct blisp_device* device,
*/
blisp_return_t blisp_common_prepare_flash(struct blisp_device* device) {
blisp_return_t ret = 0;
uint32_t previous_timeout;
printf("Sending a handshake...\n");
ret = blisp_device_handshake(device, false);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to handshake with device.\n");
return ret;
}
printf("Handshake successful!\nGetting chip info...\n");
struct blisp_boot_info boot_info;
// We may already be in communication with the chip from a previous
// invocation of this command. In that case, it will not respond to our
// handshake. We detect this by trying to send a command to it, using a
// (relatively) short timeout.
//
// NOTE: This appears to be how BouffaloLab software does it as well.
//
// NOTE: Modifying the timeout is mandatory for BL808;
// see blisp.c:blisp_device_init()
previous_timeout = device->serial_timeout;
device->serial_timeout = 500;
printf("Testing if we can skip the handshake...\n");
ret = blisp_device_get_boot_info(device, &boot_info);
device->serial_timeout = previous_timeout;
if (ret == BLISP_OK) {
printf("Skipping handshake!\n");
} else {
printf("We can't; ignore the previous error.\n");
printf("Sending a handshake...\n");
ret = blisp_device_handshake(device, false);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to handshake with device, ret: %d\n", ret);
return ret;
}
printf("Handshake successful!\nGetting chip info...\n");
ret = blisp_device_get_boot_info(device, &boot_info);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to get boot info, ret: %d\n", ret);
return ret;
}
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to get boot info.\n");
return ret;
}
// TODO: Do we want this to print in big endian to match the output
// of Bouffalo's software?
if (device->chip->type == BLISP_CHIP_BL70X) {
printf(
"BootROM version %d.%d.%d.%d, ChipID: "
"%02X%02X%02X%02X%02X%02X%02X%02X\n",
boot_info.boot_rom_version[0], boot_info.boot_rom_version[1],
boot_info.boot_rom_version[2], boot_info.boot_rom_version[3],
boot_info.chip_id[0], boot_info.chip_id[1], boot_info.chip_id[2],
boot_info.chip_id[3], boot_info.chip_id[4], boot_info.chip_id[5],
boot_info.chip_id[6], boot_info.chip_id[7]);
} else {
printf(
"BootROM version %d.%d.%d.%d, ChipID: "
"%02X%02X%02X%02X%02X%02X\n",
boot_info.boot_rom_version[0], boot_info.boot_rom_version[1],
boot_info.boot_rom_version[2], boot_info.boot_rom_version[3],
boot_info.chip_id[0], boot_info.chip_id[1], boot_info.chip_id[2],
boot_info.chip_id[3], boot_info.chip_id[4], boot_info.chip_id[5]);
}
if (device->chip->type == BLISP_CHIP_BL808) {
printf("Setting clock parameters ...\n");
ret = bl808_load_clock_para(device, true, device->current_baud_rate);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to set clock parameters, ret: %d\n", ret);
return ret;
}
printf("Setting flash parameters ...\n");
ret = bl808_load_flash_para(device);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to set flash parameters, ret: %d\n", ret);
return ret;
}
}
printf(
"BootROM version %d.%d.%d.%d, ChipID: "
"%02X%02X%02X%02X%02X%02X%02X%02X\n",
boot_info.boot_rom_version[0], boot_info.boot_rom_version[1],
boot_info.boot_rom_version[2], boot_info.boot_rom_version[3],
boot_info.chip_id[0], boot_info.chip_id[1], boot_info.chip_id[2],
boot_info.chip_id[3], boot_info.chip_id[4], boot_info.chip_id[5],
boot_info.chip_id[6], boot_info.chip_id[7]);
if (device->chip->load_eflash_loader == NULL) {
return BLISP_OK;
@@ -175,20 +119,20 @@ blisp_return_t blisp_common_prepare_flash(struct blisp_device* device) {
ret = blisp_device_check_image(device);
if (ret != 0) {
fprintf(stderr, "Failed to check image, ret: %d\n", ret);
fprintf(stderr, "Failed to check image.\n");
goto exit1;
}
ret = blisp_device_run_image(device);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to run image, ret: %d\n", ret);
fprintf(stderr, "Failed to run image.\n");
goto exit1;
}
printf("Sending a handshake...\n");
ret = blisp_device_handshake(device, true);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to handshake with device, ret: %d\n", ret);
fprintf(stderr, "Failed to handshake with device.\n");
goto exit1;
}
printf("Handshake with eflash_loader successful.\n");
@@ -197,4 +141,4 @@ exit1:
free(eflash_loader_buffer);
return ret;
}
}
+2 -7
View File
@@ -6,13 +6,8 @@
#include <blisp.h>
#include <argtable3.h>
// https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html
#define DEFAULT_BAUDRATE 460800
#define STR(x) #x
#define XSTR(x) STR(x)
blisp_return_t blisp_common_prepare_flash(struct blisp_device* device);
int32_t blisp_common_prepare_flash(struct blisp_device* device);
void blisp_common_progress_callback(uint32_t current_value, uint32_t max_value);
blisp_return_t blisp_common_init_device(struct blisp_device* device, struct arg_str* port_name, struct arg_str* chip_type, uint32_t baudrate);
int32_t blisp_common_init_device(struct blisp_device* device, struct arg_str* port_name, struct arg_str* chip_type);
#endif // BLISP_COMMON_H
@@ -1,7 +1,6 @@
list(APPEND ADD_INCLUDE
"${CMAKE_CURRENT_SOURCE_DIR}/bin"
"${CMAKE_CURRENT_SOURCE_DIR}/dfu"
"${CMAKE_CURRENT_SOURCE_DIR}/hex"
"${CMAKE_CURRENT_SOURCE_DIR}"
)
@@ -13,7 +12,6 @@ add_library(file_parsers STATIC
"${CMAKE_CURRENT_SOURCE_DIR}/bin/bin_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_crc.c"
"${CMAKE_CURRENT_SOURCE_DIR}/hex/hex_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/parse_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/get_file_contents.c"
)
@@ -21,7 +19,6 @@ add_library(file_parsers STATIC
target_include_directories(file_parsers PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/bin
${CMAKE_CURRENT_SOURCE_DIR}/dfu
${CMAKE_CURRENT_SOURCE_DIR}/hex
${CMAKE_CURRENT_SOURCE_DIR}
)
@@ -78,7 +78,6 @@ int dfu_file_parse(const char* file_path_on_disk,
size_t* payload_address) {
uint8_t* dfu_file_contents = NULL;
ssize_t file_size = get_file_contents(file_path_on_disk, &dfu_file_contents);
// Bubble up the result if it was an error instead of size (a negative value)
if (file_size < 0) {
return file_size;
}
@@ -1,10 +1,31 @@
add_executable(dfu_file_test test_dfu_file.cpp ../dfu_file.c ../dfu_crc.c ../../get_file_contents.c)
enable_language(CXX)
enable_testing()
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.11.0
)
FetchContent_MakeAvailable(googletest)
add_library(GTest::GTest INTERFACE IMPORTED)
target_link_libraries(GTest::GTest INTERFACE gtest_main)
add_executable(dfu_file_test test_dfu_file.cpp ../dfu_file.c ../dfu_crc.c)
target_link_libraries(dfu_file_test
PRIVATE
GTest::GTest
)
include(GoogleTest)
include_directories(dfu_file_test PRIVATE ../ ../../)
target_compile_definitions(dfu_file_test PUBLIC "SOURCE_DIR=\"${CMAKE_SOURCE_DIR}\"")
gtest_discover_tests(dfu_file_test)
include_directories(dfu_file_test PRIVATE ../)
add_test(dfu_file_test_gtests dfu_file_test)
configure_file(Config.h.in ${CMAKE_BINARY_DIR}/Config.h)
include_directories(${CMAKE_BINARY_DIR})
set(TEST_APP_NAME dfu_file_tests)
#add_custom_command(TARGET ${TEST_APP_NAME} COMMAND ./${TEST_APP_NAME} POST_BUILD)
@@ -0,0 +1,10 @@
//
// Created by ralim on 26/09/22.
//
#ifndef BLISP_CONFIG_H_IN_H
#define BLISP_CONFIG_H_IN_H
#define SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
#endif // BLISP_CONFIG_H_IN_H
@@ -2,16 +2,16 @@
// Created by ralim on 26/09/22.
//
#include <gtest/gtest.h>
#include "Config.h"
#include "dfu_file.h"
#include <gtest/gtest.h>
TEST(DFU_FILE_PARSER, ParseTestFile) {
uint8_t* payload = nullptr;
size_t payload_size = 0;
size_t payload_address = 0;
int res = dfu_file_parse(SOURCE_DIR
"/tools/blisp/src/file_parsers/dfu/tests/test.dfu",
&payload, &payload_size, &payload_address);
ASSERT_EQ(res, 1);
ASSERT_EQ(payload_size, 1337);
ASSERT_EQ(payload_address, 0x11223344);
}
uint8_t* payload = nullptr;
size_t payload_size = 0;
size_t payload_address = 0;
int res = dfu_file_parse(SOURCE_DIR "/test.dfu", &payload, &payload_size,
&payload_address);
ASSERT_EQ(res, 1);
ASSERT_EQ(payload_size, 1337);
ASSERT_EQ(payload_address, 0x11223344);
}
-261
View File
@@ -1,261 +0,0 @@
#include "hex_file.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parse_file.h"
// Convert ASCII hex character to integer
static int hex_to_int(char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return -1;
}
// Convert 2 ASCII hex characters to a byte
static int hex_byte_to_int(const char* str) {
int high = hex_to_int(str[0]);
int low = hex_to_int(str[1]);
if (high < 0 || low < 0)
return -1;
return (high << 4) | low;
}
// Parse a single Intel HEX line into the record type and data
// Returns: Record Type on success, negative error code on failure
static int parse_hex_line(const char* line,
uint8_t* data_buffer,
uint32_t* address,
uint32_t* base_address,
uint32_t* max_address,
uint32_t min_address) {
size_t len = strlen(line);
// Line must start with ':' and have at least 11 characters (:BBAAAATTCC)
if (line[0] != ':' || len < 11) {
return HEX_PARSE_ERROR_INVALID_FORMAT;
}
// Extract record fields
int byte_count = hex_byte_to_int(line + 1);
if (byte_count < 0)
return HEX_PARSE_ERROR_INVALID_FORMAT;
// Make sure line is long enough
if (len < (size_t)(11 + byte_count * 2)) {
return HEX_PARSE_ERROR_INVALID_FORMAT;
}
int addr_high = hex_byte_to_int(line + 3);
int addr_low = hex_byte_to_int(line + 5);
if (addr_high < 0 || addr_low < 0)
return HEX_PARSE_ERROR_INVALID_FORMAT;
uint16_t record_address = (addr_high << 8) | addr_low;
int record_type = hex_byte_to_int(line + 7);
if (record_type < 0)
return HEX_PARSE_ERROR_INVALID_FORMAT;
// Verify checksum
uint8_t checksum = 0;
for (int i = 1; i < 9 + byte_count * 2; i += 2) {
int value = hex_byte_to_int(line + i);
if (value < 0) {
return HEX_PARSE_ERROR_INVALID_FORMAT;
}
checksum += value;
}
int file_checksum = hex_byte_to_int(line + 9 + byte_count * 2);
if (file_checksum < 0) {
return HEX_PARSE_ERROR_INVALID_FORMAT;
}
checksum = ~checksum + 1; // Two's complement
// Verify checksum
if (checksum != file_checksum) {
return HEX_PARSE_ERROR_CHECKSUM;
}
// Process the record based on record type
switch (record_type) {
case HEX_RECORD_DATA: {
uint32_t absolute_address = *base_address + record_address;
*address = absolute_address;
// Update max address if this data extends beyond current max
if (absolute_address + byte_count > *max_address) {
*max_address = absolute_address + byte_count;
}
// Parse data bytes
for (int i = 0; i < byte_count; i++) {
int value = hex_byte_to_int(line + 9 + i * 2);
if (value < 0)
return HEX_PARSE_ERROR_INVALID_FORMAT;
// Make sure we don't write outside our buffer
if (data_buffer != NULL) {
size_t buf_offset = absolute_address - min_address + i;
data_buffer[buf_offset] = value;
}
}
break;
}
case HEX_RECORD_EOF:
// End of file, nothing to do
break;
case HEX_RECORD_EXTENDED_SEGMENT:
// Set segment base address (offset = value * 16)
if (byte_count != 2)
return HEX_PARSE_ERROR_INVALID_FORMAT;
int value_high = hex_byte_to_int(line + 9);
int value_low = hex_byte_to_int(line + 11);
if (value_high < 0 || value_low < 0)
return HEX_PARSE_ERROR_INVALID_FORMAT;
*base_address = ((value_high << 8) | value_low) << 4;
break;
case HEX_RECORD_EXTENDED_LINEAR:
// Set high-order 16 bits of address
if (byte_count != 2)
return HEX_PARSE_ERROR_INVALID_FORMAT;
value_high = hex_byte_to_int(line + 9);
value_low = hex_byte_to_int(line + 11);
if (value_high < 0 || value_low < 0)
return HEX_PARSE_ERROR_INVALID_FORMAT;
*base_address = ((value_high << 8) | value_low) << 16;
break;
case HEX_RECORD_START_LINEAR:
// Start linear address - store as a potential entry point
// but not crucial for firmware extraction
break;
case HEX_RECORD_START_SEGMENT:
// Start segment address - similar to above
break;
default:
return HEX_PARSE_ERROR_UNSUPPORTED_RECORD;
}
return record_type;
}
int hex_file_parse(const char* file_path_on_disk,
uint8_t** payload,
size_t* payload_length,
size_t* payload_address) {
FILE* file = fopen(file_path_on_disk, "r");
if (!file) {
fprintf(stderr, "Could not open file %s for reading\n", file_path_on_disk);
return PARSED_ERROR_CANT_OPEN_FILE;
}
// First pass: Find start and end addresses, and thus size of the payload
char line[512];
uint32_t base_address = 0;
uint32_t address = 0;
uint32_t min_address = 0xFFFFFFFF;
uint32_t max_address = 0;
bool found_data = false;
// First pass to determine memory range
while (fgets(line, sizeof(line), file)) {
size_t len = strlen(line);
// Trim trailing newline and carriage return
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
line[--len] = 0;
}
if (len == 0 || line[0] != ':')
continue;
int result =
parse_hex_line(line, NULL, &address, &base_address, &max_address, 0);
if (result < 0) {
fclose(file);
return result;
}
// Check if this is a data record (type 0)
if (result == HEX_RECORD_DATA) {
found_data = true;
if (address < min_address) {
min_address = address;
}
}
// If we hit EOF record, we're done
if (result == HEX_RECORD_EOF) {
break;
}
}
// If no data was found, return error
if (!found_data) {
fclose(file);
return HEX_PARSE_ERROR_INVALID_FORMAT;
}
// Calculate payload size
size_t size = max_address - min_address;
if (size > (1024 * 1024 * 128)) { // Limit to 128 MB
fclose(file);
return HEX_PARSE_ERROR_TOO_LARGE;
}
// Allocate memory for the payload
*payload = (uint8_t*)calloc(size, sizeof(uint8_t));
if (!*payload) {
fclose(file);
return -1;
}
// Clear the memory to ensure all bytes are initialized
memset(*payload, 0, size);
// Second pass: actually parse the data and fill out the buffer with the data
rewind(file);
base_address = 0;
while (fgets(line, sizeof(line), file)) {
size_t len = strlen(line);
// Trim trailing newline and carriage return
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
line[--len] = 0;
}
if (len == 0 || line[0] != ':')
continue;
// When parsing for real, data is written to the payload buffer
// with addresses relative to min_address
uint32_t dummy_max = 0;
int result = parse_hex_line(line, *payload, &address, &base_address,
&dummy_max, min_address);
if (result < 0) {
free(*payload);
*payload = NULL;
fclose(file);
return result;
}
// If we hit EOF record, we're done
if (result == HEX_RECORD_EOF) {
break;
}
}
fclose(file);
// Set output parameters
*payload_length = size;
*payload_address = min_address;
return 0;
}
@@ -1,49 +0,0 @@
//
// Created for Intel HEX file parsing
//
#ifndef BLISP_HEX_FILE_H
#define BLISP_HEX_FILE_H
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
// Error codes specific to hex parsing
#define HEX_PARSE_ERROR_INVALID_FORMAT -0x2001
#define HEX_PARSE_ERROR_CHECKSUM -0x2002
#define HEX_PARSE_ERROR_UNSUPPORTED_RECORD -0x2003
#define HEX_PARSE_ERROR_TOO_LARGE -0x2004
// Intel HEX record types
typedef enum {
HEX_RECORD_DATA = 0x00, // Data record
HEX_RECORD_EOF = 0x01, // End of file record
HEX_RECORD_EXTENDED_SEGMENT = 0x02, // Extended segment address record
HEX_RECORD_START_SEGMENT = 0x03, // Start segment address record
HEX_RECORD_EXTENDED_LINEAR = 0x04, // Extended linear address record
HEX_RECORD_START_LINEAR = 0x05 // Start linear address record
} hex_record_type_t;
// Parse an Intel HEX file and return a contiguous memory block
// Parameters:
// file_path_on_disk: Path to the Intel HEX file
// payload: Pointer to the buffer that will hold the parsed data
// payload_length: Size of the payload
// payload_address: Start address of the payload
// Returns:
// 0 on success, negative value on error
int hex_file_parse(const char* file_path_on_disk,
uint8_t** payload,
size_t* payload_length,
size_t* payload_address);
#ifdef __cplusplus
};
#endif
#endif // BLISP_HEX_FILE_H
@@ -1,10 +0,0 @@
add_executable(hex_file_test test_hex_file.cpp ../hex_file.c )
target_link_libraries(hex_file_test
PRIVATE
GTest::GTest
)
include(GoogleTest)
include_directories(hex_file_test PRIVATE ../ ../../)
target_compile_definitions(hex_file_test PUBLIC "SOURCE_DIR=\"${CMAKE_SOURCE_DIR}\"")
gtest_discover_tests(hex_file_test)
@@ -1,9 +0,0 @@
:02000004230FC8
:10FC0000400196000500000021005A000200070094
:10FC10000100000000001E000000000000000000C5
:10FC2000000000000000040001007602A40184032B
:10FC3000000000000A0001000700000000000000B2
:10FC4000140000001A000100000000000000040081
:10FC50005A00010082005A008C001E00A5001E0000
:10FC60008C001E005A001E00020000000000000070
:00000001FF
@@ -1,47 +0,0 @@
// Intel hex file parser test
#include <gtest/gtest.h>
#include "hex_file.h"
#include "parse_file.h"
TEST(HEX_FILE_PARSER, ParseTestFile) {
uint8_t* payload = nullptr;
size_t payload_size = 0;
size_t payload_address = 0;
int res = hex_file_parse(SOURCE_DIR
"/tools/blisp/src/file_parsers/hex/tests/test.hex",
&payload, &payload_size, &payload_address);
// Shall return 0 on success
ASSERT_EQ(res, 0);
// The expected base address is 0x230F0000 + 0xFC00 = 0x230FFC00
ASSERT_EQ(payload_address, 0x230FFC00);
// There are 7 data records of 16 bytes each, so payload size should be 0x70
// (112 bytes)
ASSERT_EQ(payload_size, 0x70);
// Optionally, check the first few bytes for expected values
ASSERT_EQ(payload[0], 0x40);
ASSERT_EQ(payload[1], 0x01);
ASSERT_EQ(payload[2], 0x96);
ASSERT_EQ(payload[3], 0x00);
// Clean up
free(payload);
}
TEST(HEX_FILE_PARSER, ParseNonExistentFile) {
uint8_t* payload = nullptr;
size_t payload_size = 0;
size_t payload_address = 0;
int res = hex_file_parse(SOURCE_DIR "/non_existent_file.hex", &payload,
&payload_size, &payload_address);
ASSERT_EQ(res, PARSED_ERROR_CANT_OPEN_FILE);
}
TEST(HEX_FILE_PARSER, ParseInvalidFormat) {
// This test would require creating an invalid hex file
// For simplicity, we'll skip actual implementation
// but in a real test suite we would create a file with invalid format
// and verify that it returns HEX_PARSE_ERROR_INVALID_FORMAT
}
+2 -8
View File
@@ -2,7 +2,6 @@
#include <string.h>
#include "bin_file.h"
#include "dfu_file.h"
#include "hex_file.h"
const char* get_filename_ext(const char* filename) {
const char* dot = strrchr(filename, '.');
@@ -28,13 +27,8 @@ int parse_firmware_file(const char* file_path_on_disk,
res = bin_file_parse(file_path_on_disk, &parsed_results->payload,
&parsed_results->payload_length,
&parsed_results->payload_address);
} else if (strncmp(ext, "hex", 3) == 0 || strncmp(ext, "HEX", 3) == 0) {
printf("Input file identified as a .hex file\n");
// Intel HEX file
res = hex_file_parse(file_path_on_disk, &parsed_results->payload,
&parsed_results->payload_length,
&parsed_results->payload_address);
}
// If we wanted to support hex files, here would be where
// Normalise address, some builds will base the firmware at flash start but
// for the flasher we use 0 base (i.e. offsets into flash)
@@ -46,4 +40,4 @@ int parse_firmware_file(const char* file_path_on_disk,
parsed_results->needs_boot_struct = parsed_results->payload_address == 0;
return res;
}
}
@@ -2,7 +2,6 @@
#define PARSE_FILE_H_
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* ssize_t */
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
+1 -1
View File
@@ -45,7 +45,7 @@ int8_t args_parse_exec(int argc, char** argv) {
print_help();
return BLISP_OK;
} else if (version->count) {
printf("blisp v0.0.5\n");
printf("blisp v0.0.4\n");
printf("Copyright (C) 2023 Marek Kraus and PINE64 Community\n");
return BLISP_OK;
}
-1
View File
@@ -10,7 +10,6 @@
// to free an allocated buffer on the caller.nn
#include <stdlib.h>
#include <mach-o/dyld.h>
static void util_get_executable_path(char* buffer_out, uint32_t max_size) {
assert(max_size >= PATH_MAX); // n.b. 1024 on MacOS. 4K on most Linux.