Author SHA1 Message Date
Marek Kraus b583ec46f9 Add run firmware in RAM feature 2024-06-19 18:09:16 +02:00
47 changed files with 400 additions and 1776 deletions
-1
View File
@@ -1 +0,0 @@
use flake .
+16 -58
View File
@@ -2,31 +2,15 @@ name: Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
check-nix-flake:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
- name: Check Nix Flake
run: nix flake check --print-build-logs
check-nix-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
- name: Build package
run: nix build --print-build-logs
build-windows: build-windows:
runs-on: windows-2022 runs-on: windows-2022
defaults: defaults:
run: run:
shell: cmd shell: cmd
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
submodules: "recursive" submodules: 'recursive'
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- name: Build blisp tool - name: Build blisp tool
run: | run: |
@@ -35,9 +19,9 @@ jobs:
cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release cmake --build . --config Release
- name: Upload results - name: Upload results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: blips-windows-x86_64 name: blips-windows-x86_64.zip
path: | path: |
build/tools/blisp/Release/blisp.exe build/tools/blisp/Release/blisp.exe
if-no-files-found: error if-no-files-found: error
@@ -45,9 +29,9 @@ jobs:
build-macos: build-macos:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
submodules: "recursive" submodules: 'recursive'
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- name: Build blisp tool - name: Build blisp tool
run: | run: |
@@ -56,9 +40,9 @@ jobs:
cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build . cmake --build .
- name: Upload results - name: Upload results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: blips-apple-universal name: blips-apple-universal.zip
path: | path: |
build/tools/blisp/blisp build/tools/blisp/blisp
if-no-files-found: error if-no-files-found: error
@@ -66,9 +50,9 @@ jobs:
build-linux: build-linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
submodules: "recursive" submodules: 'recursive'
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- name: Build blisp tool - name: Build blisp tool
run: | run: |
@@ -77,9 +61,9 @@ jobs:
cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release cmake .. -DBLISP_BUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build . cmake --build .
- name: Upload results - name: Upload results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: blips-linux-x86_64 name: blips-linux-x86_64.zip
path: | path: |
build/tools/blisp/blisp build/tools/blisp/blisp
if-no-files-found: error if-no-files-found: error
@@ -99,9 +83,9 @@ jobs:
- arch: riscv64 - arch: riscv64
distro: ubuntu_latest distro: ubuntu_latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
submodules: "recursive" submodules: 'recursive'
- uses: uraimo/run-on-arch-action@v2 - uses: uraimo/run-on-arch-action@v2
name: Build artifact name: Build artifact
id: build id: build
@@ -149,35 +133,9 @@ jobs:
echo "Produced artifact at /artifacts/${artifact_name}" echo "Produced artifact at /artifacts/${artifact_name}"
- name: Upload results - name: Upload results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: blisp-linux-${{ matrix.arch }} name: blisp-linux-${{ matrix.arch }}.zip
path: | path: |
artifacts/blisp-* artifacts/blisp-*
if-no-files-found: error 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
-1
View File
@@ -78,4 +78,3 @@ fabric.properties
build/ build/
.DS_Store .DS_Store
.cache/
+3
View File
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project> </project>
+14 -42
View File
@@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
# set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
project(blisp C) project(blisp C)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
@@ -11,22 +10,10 @@ option(COMPILE_TESTS "Compile the tests" OFF)
add_library(libblisp_obj OBJECT add_library(libblisp_obj OBJECT
lib/blisp.c lib/blisp.c
lib/blisp_easy.c
lib/blisp_util.c
lib/chip/blisp_chip_bl60x.c lib/chip/blisp_chip_bl60x.c
lib/chip/blisp_chip_bl70x.c lib/chip/blisp_chip_bl70x.c lib/blisp_easy.c)
lib/chip/blisp_chip_bl808.c)
target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/include/) 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) set_property(TARGET libblisp_obj PROPERTY POSITION_INDEPENDENT_CODE 1)
@@ -42,31 +29,32 @@ set(BLISP_PUBLIC_HEADERS
set_target_properties(libblisp PROPERTIES set_target_properties(libblisp PROPERTIES
PUBLIC_HEADER "${BLISP_PUBLIC_HEADERS}" PUBLIC_HEADER "${BLISP_PUBLIC_HEADERS}"
VERSION 0.0.5 VERSION 0.0.4
SOVERSION 1 SOVERSION 1
LIBRARY_OUTPUT_DIRECTORY "shared" LIBRARY_OUTPUT_DIRECTORY "shared"
OUTPUT_NAME "blisp") OUTPUT_NAME "blisp")
set_target_properties(libblisp_static PROPERTIES set_target_properties(libblisp_static PROPERTIES
PUBLIC_HEADER "${BLISP_PUBLIC_HEADERS}" PUBLIC_HEADER "${BLISP_PUBLIC_HEADERS}"
VERSION 0.0.5 VERSION 0.0.4
SOVERSION 1 SOVERSION 1
ARCHIVE_OUTPUT_DIRECTORY "static" ARCHIVE_OUTPUT_DIRECTORY "static"
OUTPUT_NAME "blisp") OUTPUT_NAME "blisp")
if(BLISP_USE_SYSTEM_LIBRARIES) if(BLISP_USE_SYSTEM_LIBRARIES)
find_package(Libserialport REQUIRED) find_package(PkgConfig)
target_link_libraries(libblisp PUBLIC Libserialport::Libserialport) pkg_search_module(LIBSERIALPORT REQUIRED libserialport)
target_link_libraries(libblisp_static PUBLIC Libserialport::Libserialport) target_link_libraries(libblisp PUBLIC ${LIBSERIALPORT_LIBRARIES})
target_include_directories(libblisp_obj PUBLIC ${Libserialport_INCLUDE_DIRS}) target_link_libraries(libblisp_static PUBLIC ${LIBSERIALPORT_LIBRARIES})
target_include_directories(libblisp_obj PUBLIC ${LIBSERIALPORT_INCLUDE_DIRS})
else() else()
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
target_sources(libblisp_obj PRIVATE target_sources(libblisp_obj PRIVATE
${CMAKE_SOURCE_DIR}/vendor/libserialport/serialport.c ${CMAKE_SOURCE_DIR}/vendor/libserialport/serialport.c
${CMAKE_SOURCE_DIR}/vendor/libserialport/timing.c) ${CMAKE_SOURCE_DIR}/vendor/libserialport/timing.c)
target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/vendor/libserialport) target_include_directories(libblisp_obj PRIVATE ${CMAKE_SOURCE_DIR}/vendor/libserialport)
endif() endif()
if(WIN32) if(WIN32)
target_link_libraries(libblisp PRIVATE Setupapi.lib) target_link_libraries(libblisp PRIVATE Setupapi.lib)
@@ -117,21 +105,5 @@ endif()
if(COMPILE_TESTS) if(COMPILE_TESTS)
# Bring in googletest & C++ add_subdirectory(tools/blisp/src/cmd/dfu/tests)
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)
endif(COMPILE_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
+3 -12
View File
@@ -1,7 +1,7 @@
[![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) [![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) [![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" /> <img src="./img/Gradient-white-blue-03.png" align="left" width="60" > <br clear="left" />
# BLISP # BLISP
@@ -17,7 +17,7 @@ Bouffalo Labs ISP (in-system-programming) tool & library: an open source tool to
<br> <br>
## Supported Devices ## 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 | | 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" /> | | 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" /> | | 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" /> |
@@ -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. 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 This is really only useful for debugging systems-level issues withing
the device or blisp itself. 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 ## Troubleshooting
-49
View File
@@ -1,49 +0,0 @@
{
lib,
self,
stdenv,
fetchFromGitHub,
argtable,
cmake,
libserialport,
pkg-config,
testers,
IOKit ? null,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "blisp";
version = "0.0.5-unstable";
src = self;
nativeBuildInputs = [
cmake
pkg-config
];
buildInputs = [
argtable
libserialport
] ++ lib.optional stdenv.hostPlatform.isDarwin IOKit;
cmakeFlags = [
"-DBLISP_BUILD_CLI=ON"
"-DBLISP_USE_SYSTEM_LIBRARIES=ON"
];
env.NIX_CFLAGS_COMPILE = lib.optionalString stdenv.hostPlatform.isDarwin "-Wno-error=implicit-function-declaration";
passthru.tests.version = testers.testVersion {
package = finalAttrs.finalPackage;
version = "v${finalAttrs.version}";
};
meta = with lib; {
description = "In-System-Programming (ISP) tool & library for Bouffalo Labs RISC-V Microcontrollers and SoCs";
license = licenses.mit;
mainProgram = "blisp";
homepage = "https://github.com/pine64/blisp";
platforms = platforms.unix;
maintainers = [ maintainers.bdd ];
};
})
-79
View File
@@ -1,79 +0,0 @@
# SPDX-License-Identifier: MIT
#[=======================================================================[.rst:
FindLibserialport
-------
Finds the sigrok serial port library (``libserialport``)
Imported Targets
^^^^^^^^^^^^^^^^
This module defines the following imported targets, if found:
``Libserialport::Libserialport``
The serialport library
Result Variables
^^^^^^^^^^^^^^^^
This module will define the following variables:
``Libserialport_FOUND``
True if the system has the serialport library.
``Libserialport_VERSION``
The version of the serialport library which was found.
``Libserialport_INCLUDE_DIRS``
Include directories needed to use ``libserialport``.
``Libserialport_LIBRARIES``
Libraries needed to link to ``libserialport``.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``Libserialport_INCLUDE_DIR``
The directory containing ``libserialport.h``.
``Libserialport_LIBRARY``
The path to the ``libserialport`` library.
#]=======================================================================]
find_package(PkgConfig)
pkg_check_modules(PC_Libserialport QUIET libserialport)
find_path(Libserialport_INCLUDE_DIR
NAMES libserialport.h
PATHS "${PC_Libserialport_INCLUDE_DIRS}"
)
find_library(Libserialport_LIBRARY
NAMES serialport
HINTS "${PC_Libserialport_LIBRARY_DIRS}"
)
set(Foo_VERSION ${PC_Foo_VERSION})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libserialport
FOUND_VAR Libserialport_FOUND
REQUIRED_VARS
Libserialport_LIBRARY
Libserialport_INCLUDE_DIR
VERSION_VAR Libserialport_VERSION
)
if(Libserialport_FOUND)
set(Libserialport_LIBRARIES ${Libserialport_LIBRARY})
set(Libserialport_INCLUDE_DIRS ${Libserialport_INCLUDE_DIR})
set(Libserialport_DEFINITIONS ${PC_Liberialport_CFLAGS_OTHER})
endif()
if(Libserialport_FOUND AND NOT TARGET Libserialport::Libserialport)
add_library(Libserialport::Libserialport UNKNOWN IMPORTED)
set_target_properties(Libserialport::Libserialport PROPERTIES
IMPORTED_LOCATION "${Libserialport_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${PC_Libserialport_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${Libserialport_INCLUDE_DIR}"
)
endif()
-9
View File
@@ -1,9 +0,0 @@
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).defaultNix
Generated
-27
View File
@@ -1,27 +0,0 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1731319897,
"narHash": "sha256-PbABj4tnbWFMfBp6OcUK5iGy1QY+/Z96ZcLpooIbuEI=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "dc460ec76cbff0e66e269457d7b728432263166c",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
-44
View File
@@ -1,44 +0,0 @@
{
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs =
{ self, nixpkgs, ... }@inputs:
let
systems = [
"x86_64-linux"
"aarch64-linux"
];
forEachSystem = nixpkgs.lib.genAttrs systems;
in
{
packages = forEachSystem (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
with pkgs;
{
blisp = callPackage ./blisp.nix { inherit self; };
default = self.packages.${system}.blisp;
}
);
devShells = forEachSystem (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
with pkgs;
{
default = mkShell {
name = "blisp-dev";
nativeBuildInputs = [ self.packages.${system}.default ];
};
}
);
};
}
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 B

+26 -35
View File
@@ -16,7 +16,6 @@ struct blisp_segment_header {
struct blisp_device { struct blisp_device {
struct blisp_chip* chip; struct blisp_chip* chip;
void* serial_port; void* serial_port;
uint32_t serial_timeout; // in ms
bool is_usb; bool is_usb;
uint32_t current_baud_rate; uint32_t current_baud_rate;
uint8_t rx_buffer[5000]; // TODO: 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 // TODO: Refactor variable names, so all will follow same semantic, like
// image_run, image_check etc. // image_run, image_check etc.
blisp_return_t blisp_device_init(struct blisp_device* device, struct blisp_chip* chip); int32_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, int32_t blisp_device_open(struct blisp_device* device, const char* port_name);
uint32_t baudrate); int32_t blisp_device_handshake(struct blisp_device* device, bool in_ef_loader);
blisp_return_t blisp_device_handshake(struct blisp_device* device, bool in_ef_loader); int32_t blisp_device_get_boot_info(struct blisp_device* device,
blisp_return_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boot_info* boot_info);
struct blisp_boot_info* boot_info); int32_t blisp_device_load_boot_header(struct blisp_device* device,
blisp_return_t blisp_device_load_boot_header(struct blisp_device* device, uint8_t* boot_header);
uint8_t* boot_header); int32_t blisp_device_load_segment_header(
blisp_return_t blisp_device_load_segment_header(
struct blisp_device* device, struct blisp_device* device,
struct blisp_segment_header* segment_header); struct blisp_segment_header* segment_header);
blisp_return_t blisp_device_load_segment_data(struct blisp_device* device, int32_t blisp_device_load_segment_data(struct blisp_device* device,
uint8_t* segment_data, uint8_t* segment_data,
uint32_t segment_data_length); uint32_t segment_data_length);
blisp_return_t blisp_device_write_memory(struct blisp_device* device, int32_t blisp_device_write_memory(struct blisp_device* device,
uint32_t address, uint32_t address,
uint32_t value, uint32_t value,
bool wait_for_res); bool wait_for_res);
blisp_return_t blisp_device_check_image(struct blisp_device* device); int32_t blisp_device_check_image(struct blisp_device* device);
blisp_return_t blisp_device_run_image(struct blisp_device* device); int32_t blisp_device_run_image(struct blisp_device* device);
blisp_return_t blisp_device_flash_erase(struct blisp_device* device, int32_t blisp_device_flash_erase(struct blisp_device* device,
uint32_t start_address, uint32_t start_address,
uint32_t end_address); uint32_t end_address);
blisp_return_t blisp_device_chip_erase(struct blisp_device* device); int32_t blisp_device_flash_write(struct blisp_device* device,
blisp_return_t blisp_device_flash_write(struct blisp_device* device, uint32_t start_address,
uint32_t start_address, uint8_t* payload,
uint8_t* payload, uint32_t payload_size);
uint32_t payload_size); int32_t blisp_device_program_check(struct blisp_device* device);
int32_t blisp_device_reset(struct blisp_device* device);
blisp_return_t blisp_device_program_check(struct blisp_device* device);
blisp_return_t blisp_device_reset(struct blisp_device* device);
void blisp_device_close(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
-3
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_bl808;
extern struct blisp_chip blisp_chip_bl61x; extern struct blisp_chip blisp_chip_bl61x;
extern struct bl808_bootheader_t bl808_header;
void fill_crcs(struct bl808_bootheader_t *bh);
#endif #endif
+4 -1
View File
@@ -8,7 +8,10 @@
struct blisp_easy_transport { struct blisp_easy_transport {
uint8_t type; // 0 - memory, 1 - FILE file_handle uint8_t type; // 0 - memory, 1 - FILE file_handle
union { union {
FILE* file_handle; struct {
FILE* file_handle;
int64_t file_size;
} file;
struct { struct {
void* data_location; void* data_location;
uint32_t data_size; uint32_t data_size;
-212
View File
@@ -9,12 +9,6 @@
#include <assert.h> #include <assert.h>
#include <stdint.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) #pragma pack(push, 1)
typedef struct { typedef struct {
@@ -173,212 +167,6 @@ struct blflash_segment_header {
static_assert(sizeof(struct blflash_segment_header) == 16, static_assert(sizeof(struct blflash_segment_header) == 16,
"Segment header have wrong size"); "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) #pragma pack(pop)
#endif #endif
+38 -8
View File
@@ -2,20 +2,35 @@
#ifndef _BLISP_UTIL_H #ifndef _BLISP_UTIL_H
#define _BLISP_UTIL_H #define _BLISP_UTIL_H
#include <stdint.h> #include <stdarg.h>
#include <stdio.h>
#ifdef WIN32 #ifdef WIN32
# include <windows.h> #include <windows.h>
#else #else
# include <time.h> #include <time.h>
#endif #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); static void sleep_ms(int milliseconds) {
#ifdef WIN32
uint32_t crc32_calculate(const void *data, size_t data_len); 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 * * 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 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
}; };
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 #endif
+19 -211
View File
@@ -11,15 +11,11 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif #endif
#include <blisp_struct.h>
#define DEBUG #define DEBUG
static void drain(struct sp_port* port) { static void drain(struct sp_port* port) {
#if defined(__APPLE__) || defined(__FreeBSD__) #if defined(__APPLE__) || defined(__FreeBSD__)
sp_drain(port); sp_drain(port);
#else
(void)port; // unused
#endif #endif
} }
@@ -27,24 +23,12 @@ blisp_return_t blisp_device_init(struct blisp_device* device,
struct blisp_chip* chip) { struct blisp_chip* chip) {
device->chip = chip; device->chip = chip;
device->is_usb = false; 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; return BLISP_OK;
} }
blisp_return_t blisp_device_open(struct blisp_device* device, blisp_return_t blisp_device_open(struct blisp_device* device,
const char* port_name, const char* port_name) {
uint32_t baudrate) { blisp_return_t ret;
enum sp_return ret;
struct sp_port* serial_port = NULL; struct sp_port* serial_port = NULL;
if (port_name != NULL) { if (port_name != NULL) {
@@ -98,7 +82,11 @@ blisp_return_t blisp_device_open(struct blisp_device* device,
int vid, pid; int vid, pid;
sp_get_port_usb_vid_pid(serial_port, &vid, &pid); sp_get_port_usb_vid_pid(serial_port, &vid, &pid);
device->is_usb = pid == 0xFFFF; 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 #if 0
int fd; int fd;
@@ -157,9 +145,8 @@ blisp_return_t blisp_receive_response(struct blisp_device* device,
bool expect_payload) { bool expect_payload) {
// TODO: Check checksum // TODO: Check checksum
int ret; int ret;
struct sp_port* serial_port = device->serial_port; 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) { if (ret < 2) {
blisp_dlog("Failed to receive response, ret: %d", ret); blisp_dlog("Failed to receive response, ret: %d", ret);
return BLISP_ERR_NO_RESPONSE; 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, blisp_return_t blisp_device_handshake(struct blisp_device* device,
bool in_ef_loader) { bool in_ef_loader) {
int ret; int ret;
bool ok = false;
uint8_t handshake_buffer[600]; uint8_t handshake_buffer[600];
struct sp_port* serial_port = device->serial_port; 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 sleep_ms(50); // Wait a bit so BootROM can init
} }
uint32_t bytes_count = (uint32_t)(device->chip->handshake_byte_multiplier * uint32_t bytes_count = device->chip->handshake_byte_multiplier *
(float)device->current_baud_rate / 10.0f); (float)device->current_baud_rate / 10.0f;
if (bytes_count > 600) if (bytes_count > 600)
bytes_count = 600; bytes_count = 600;
memset(handshake_buffer, 'U', bytes_count); 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 sp_flush(serial_port, SP_BUF_INPUT); // Flush garbage out of RX
} }
if (device->chip->type == BLISP_CHIP_BL808) { ret = sp_blocking_read(serial_port, device->rx_buffer, 2, 50);
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);
if (ret >= 2) { if (ret >= 2) {
for (uint8_t j = 0; j < (ret - 1); j++) { if (device->rx_buffer[0] == 'O' && device->rx_buffer[1] == 'K') {
if (device->rx_buffer[j] == 'O' && device->rx_buffer[j + 1] == 'K') { return BLISP_OK;
ok = true;
}
} }
} }
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("Received no response from chip.");
blisp_dlog("Did not receive correct response from chip after 5 attempts.");
return BLISP_ERR_NO_RESPONSE; return BLISP_ERR_NO_RESPONSE;
} }
@@ -279,15 +239,13 @@ blisp_return_t blisp_device_get_boot_info(struct blisp_device* device,
if (ret < 0) if (ret < 0)
return ret; return ret;
// TODO: Endianess; this may break on big endian machines memcpy(boot_info->boot_rom_version, &device->rx_buffer[0],
memcpy(boot_info->boot_rom_version, &device->rx_buffer[0], 4); 4); // TODO: Endianess; this may break on big endian machines
if (device->chip->type == BLISP_CHIP_BL70X) { if (device->chip->type == BLISP_CHIP_BL70X) {
memcpy(boot_info->chip_id, &device->rx_buffer[16], 8); 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; return BLISP_OK;
} }
@@ -402,24 +360,13 @@ blisp_return_t blisp_device_flash_erase(struct blisp_device* device,
*(uint32_t*)(payload + 4) = end_address; *(uint32_t*)(payload + 4) = end_address;
blisp_return_t ret = blisp_send_command(device, 0x30, payload, 8, true); blisp_return_t ret = blisp_send_command(device, 0x30, payload, 8, true);
if (ret != BLISP_OK) if (ret < 0)
return ret; return ret;
do { do {
ret = blisp_receive_response(device, false); ret = blisp_receive_response(device, false);
} while (ret == BLISP_ERR_PENDING); } while (ret == BLISP_ERR_PENDING);
return ret; return 0;
}
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;
} }
blisp_return_t blisp_device_flash_write(struct blisp_device* device, blisp_return_t blisp_device_flash_write(struct blisp_device* device,
@@ -468,142 +415,3 @@ void blisp_device_close(struct blisp_device* device) {
struct sp_port* serial_port = device->serial_port; struct sp_port* serial_port = device->serial_port;
sp_close(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;
}
+9 -5
View File
@@ -19,7 +19,7 @@ static blisp_return_t blisp_easy_transport_read(
transport->data.memory.current_position += size; transport->data.memory.current_position += size;
return size; return size;
} else { } else {
return fread(buffer, size, 1, transport->data.file_handle); return fread(buffer, size, 1, transport->data.file.file_handle);
} }
} }
@@ -28,9 +28,13 @@ static blisp_return_t blisp_easy_transport_size(
if (transport->type == 0) { if (transport->type == 0) {
return transport->data.memory.data_size; return transport->data.memory.data_size;
} else { } else {
// TODO: Implement if (transport->data.file.file_size == -1) {
printf("%s() Warning: calling non-implemented function\n", __func__); FILE* handle = transport->data.file.file_handle;
return BLISP_ERR_NOT_IMPLEMENTED; fseek(handle, 0, SEEK_END);
transport->data.file.file_size = ftell(handle);
rewind(handle);
}
return transport->data.file.file_size;
} }
} }
@@ -43,7 +47,7 @@ static void blisp_easy_report_progress(blisp_easy_progress_callback callback,
} }
struct blisp_easy_transport blisp_easy_transport_new_from_file(FILE* file) { struct blisp_easy_transport blisp_easy_transport_new_from_file(FILE* file) {
struct blisp_easy_transport transport = {.type = 1, .data.file_handle = file}; struct blisp_easy_transport transport = {.type = 1, .data.file.file_handle = file, .data.file.file_size = -1};
return transport; return transport;
} }
-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) 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)); uint8_t* firmware_buf = malloc(sizeof(bl60x_eflash_loader_bin));
memcpy(firmware_buf, bl60x_eflash_loader_bin, 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 *(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) 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)); uint8_t* firmware_buf = malloc(sizeof(bl70x_eflash_loader_bin));
memcpy(firmware_buf, bl70x_eflash_loader_bin, 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 *(firmware_buf + 0xE0) = 1; // TODO: 32 MHz clock
+4 -224
View File
@@ -1,231 +1,11 @@
/* // SPDX-License-Identifier: MIT
* Some parts of this source code belongs to Bouffalo Labs
* COPYRIGHT(c) 2020 Bouffalo Lab , License: Apache
*/
#include "blisp.h" #include "blisp.h"
#include "blisp_struct.h"
#include "blisp_util.h"
#include <stddef.h>
struct blisp_chip blisp_chip_bl808 = { struct blisp_chip blisp_chip_bl808 = {
.type = BLISP_CHIP_BL808, .type = BLISP_CHIP_BL808,
.type_str = "bl808", .type_str = "bl808",
.usb_isp_available = true, // TODO: Only for BL808D :-( .usb_isp_available = true, // TODO: Only for BL808D :-(
.default_xtal = "-", // XXX: bfl software marks this as "Auto (0x07)" .default_xtal = "-", // ?
.handshake_byte_multiplier = 0.006f, .handshake_byte_multiplier = 0.003f,
.load_eflash_loader = NULL .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);
}
-9
View File
@@ -1,9 +0,0 @@
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).shellNix
+2 -12
View File
@@ -2,7 +2,7 @@ set(ARGTABLE3_ENABLE_TESTS OFF CACHE BOOL "Enable unit tests")
set(ARGTABLE3_ENABLE_EXAMPLES OFF CACHE BOOL "Enable examples") set(ARGTABLE3_ENABLE_EXAMPLES OFF CACHE BOOL "Enable examples")
#set(ARGTABLE3_REPLACE_GETOPT OFF CACHE BOOL "Replace getopt in the system C library") #set(ARGTABLE3_REPLACE_GETOPT OFF CACHE BOOL "Replace getopt in the system C library")
add_executable(blisp src/main.c src/cmd/write.c src/util.c src/common.c src/cmd/iot.c) add_executable(blisp src/main.c src/cmd/write.c src/util.c src/common.c src/cmd/iot.c src/cmd/run.c)
add_subdirectory(src/file_parsers) add_subdirectory(src/file_parsers)
@@ -20,19 +20,9 @@ target_include_directories(blisp PRIVATE
"${CMAKE_SOURCE_DIR}/include") "${CMAKE_SOURCE_DIR}/include")
target_link_libraries(blisp PRIVATE target_link_libraries(blisp PRIVATE
argtable3::argtable3 argtable3
libblisp_static file_parsers) 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) if (WIN32)
target_link_libraries(blisp PRIVATE Setupapi.lib) target_link_libraries(blisp PRIVATE Setupapi.lib)
elseif (APPLE) elseif (APPLE)
+1 -8
View File
@@ -2,14 +2,6 @@
#ifndef BLISP_CMD_H #ifndef BLISP_CMD_H
#define BLISP_CMD_H #define BLISP_CMD_H
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include <unistd.h>
#elif defined(_WIN32) || defined(WIN32)
#include <io.h>
#define R_OK 4
#define access _access
#endif
#include <stdint.h> #include <stdint.h>
#include "error_codes.h" #include "error_codes.h"
struct cmd { struct cmd {
@@ -21,6 +13,7 @@ struct cmd {
}; };
extern struct cmd cmd_write; extern struct cmd cmd_write;
extern struct cmd cmd_run;
extern struct cmd cmd_iot; extern struct cmd cmd_iot;
#endif // BLISP_CMD_H #endif // BLISP_CMD_H
+23 -64
View File
@@ -1,6 +1,5 @@
#include <argtable3.h> #include <argtable3.h>
#include <blisp_easy.h> #include <blisp_easy.h>
#include "../cmd.h" #include "../cmd.h"
#include "../common.h" #include "../common.h"
@@ -11,54 +10,21 @@ static struct arg_rex* cmd;
static struct arg_file* single_download; static struct arg_file* single_download;
static struct arg_int* single_download_location; static struct arg_int* single_download_location;
static struct arg_str *port_name, *chip_type; // TODO: Make this common 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* reset;
static struct arg_lit* chiperase;
static struct arg_end* end; 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; struct blisp_device device;
blisp_return_t ret; blisp_return_t ret;
uint32_t baud = DEFAULT_BAUDRATE; ret = blisp_common_init_device(&device, port_name, chip_type);
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]);
cmd_iot_args_print_glossary(); /* Print help to assist user */
/* No need to free memory, will now exit with ret code 1 */
return 1;
}
ret = blisp_common_init_device(&device, port_name, chip_type, baud);
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
return ret; return ret;
} }
ret = blisp_common_prepare_flash(&device); ret = blisp_common_prepare_flash(&device, true);
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
// TODO: user-friendly error messages // TODO: Error handling
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);
}
goto exit1; goto exit1;
} }
@@ -76,9 +42,9 @@ blisp_return_t blisp_single_download(void) {
printf("Erasing the area, this might take a while...\n"); printf("Erasing the area, this might take a while...\n");
ret = blisp_device_flash_erase( ret = blisp_device_flash_erase(
&device, *single_download_location->ival, &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) { if (ret != BLISP_OK) {
fprintf(stderr, "Failed to erase, ret: %d\n", ret); fprintf(stderr, "Failed to erase.\n");
goto exit2; goto exit2;
} }
@@ -89,15 +55,15 @@ blisp_return_t blisp_single_download(void) {
ret = blisp_easy_flash_write(&device, &data_transport, ret = blisp_easy_flash_write(&device, &data_transport,
*single_download_location->ival, data_file_size, *single_download_location->ival, data_file_size,
blisp_common_progress_callback); blisp_common_progress_callback);
if (ret != BLISP_OK) { if (ret < BLISP_OK) {
fprintf(stderr, "Failed to write data to flash, ret: %d\n", ret); fprintf(stderr, "Failed to write data to flash.\n");
goto exit2; goto exit2;
} }
printf("Checking program...\n"); printf("Checking program...\n");
ret = blisp_device_program_check(&device); ret = blisp_device_program_check(&device);
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
fprintf(stderr, "Failed to check program, ret: %d\n", ret); fprintf(stderr, "Failed to check program.\n");
goto exit2; goto exit2;
} }
printf("Program OK!\n"); printf("Program OK!\n");
@@ -106,7 +72,7 @@ blisp_return_t blisp_single_download(void) {
printf("Resetting the chip.\n"); printf("Resetting the chip.\n");
ret = blisp_device_reset(&device); ret = blisp_device_reset(&device);
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
fprintf(stderr, "Failed to reset chip, ret: %d\n", ret); fprintf(stderr, "Failed to reset chip.\n");
goto exit2; goto exit2;
} }
} }
@@ -123,28 +89,21 @@ exit1:
return ret; return ret;
} }
blisp_return_t cmd_iot_args_init(void) { blisp_return_t cmd_iot_args_init() {
size_t index = 0; cmd_iot_argtable[0] = cmd =
cmd_iot_argtable[index++] = cmd =
arg_rex1(NULL, NULL, "iot", NULL, REG_ICASE, NULL); 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"); 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>", arg_str0("p", "port", "<port_name>",
"Name/Path to the Serial Port (empty for search)"); "Name/Path to the Serial Port (empty for search)");
cmd_iot_argtable[index++] = baudrate = cmd_iot_argtable[3] = reset =
arg_int0("b", "baudrate", "<baud rate>",
"Serial baud rate (default: " XSTR(DEFAULT_BAUDRATE) ")");
cmd_iot_argtable[index++] = reset =
arg_lit0(NULL, "reset", "Reset chip after write"); arg_lit0(NULL, "reset", "Reset chip after write");
cmd_iot_argtable[index++] = chiperase = cmd_iot_argtable[4] = single_download =
arg_lit0(NULL, "chiperase", "Do not write any data; erase the entire chip instead");
cmd_iot_argtable[index++] = single_download =
arg_file0("s", "single-down", "<file>", "Single download file"); 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"); 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) { if (arg_nullcheck(cmd_iot_argtable) != 0) {
fprintf(stderr, "insufficient memory\n"); fprintf(stderr, "insufficient memory\n");
@@ -153,7 +112,7 @@ blisp_return_t cmd_iot_args_init(void) {
return BLISP_OK; return BLISP_OK;
} }
void cmd_iot_args_print_glossary(void) { void cmd_iot_args_print_glossary() {
fputs("Usage: blisp", stdout); fputs("Usage: blisp", stdout);
arg_print_syntax(stdout, cmd_iot_argtable, "\n"); arg_print_syntax(stdout, cmd_iot_argtable, "\n");
puts("Flashes firmware as Bouffalo's DevCube"); puts("Flashes firmware as Bouffalo's DevCube");
@@ -163,7 +122,7 @@ void cmd_iot_args_print_glossary(void) {
blisp_return_t cmd_iot_parse_exec(int argc, char** argv) { blisp_return_t cmd_iot_parse_exec(int argc, char** argv) {
int errors = arg_parse(argc, argv, cmd_iot_argtable); int errors = arg_parse(argc, argv, cmd_iot_argtable);
if (errors == 0) { 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(); return blisp_single_download();
} else { } else {
return BLISP_ERR_INVALID_COMMAND; return BLISP_ERR_INVALID_COMMAND;
@@ -175,11 +134,11 @@ blisp_return_t cmd_iot_parse_exec(int argc, char** argv) {
return BLISP_ERR_INVALID_COMMAND; 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"); arg_print_syntax(stdout, cmd_iot_argtable, "\n");
} }
void cmd_iot_free(void) { void cmd_iot_free() {
arg_freetable(cmd_iot_argtable, arg_freetable(cmd_iot_argtable,
sizeof(cmd_iot_argtable) / sizeof(cmd_iot_argtable[0])); sizeof(cmd_iot_argtable) / sizeof(cmd_iot_argtable[0]));
} }
+119
View File
@@ -0,0 +1,119 @@
#include <argtable3.h>
#include <blisp_easy.h>
#include "../cmd.h"
#include "../common.h"
#define REG_EXTENDED 1
#define REG_ICASE (REG_EXTENDED << 1)
static struct arg_rex* cmd;
static struct arg_str *port_name, *chip_type; // TODO: Make this common
static struct arg_lit* reset;
static struct arg_end* end;
static struct arg_file* binary_to_run;
static void* cmd_run_argtable[6];
blisp_return_t cmd_run_args_init() {
cmd_run_argtable[0] = cmd =
arg_rex1(NULL, NULL, "run", NULL, REG_ICASE, NULL);
cmd_run_argtable[1] = chip_type =
arg_str1("c", "chip", "<chip_type>", "Chip Type");
cmd_run_argtable[2] = port_name =
arg_str0("p", "port", "<port_name>",
"Name/Path to the Serial Port (empty for search)");
cmd_run_argtable[3] = reset =
arg_lit0(NULL, "reset", "Reset chip after write");
cmd_run_argtable[4] = binary_to_run =
arg_file1(NULL, NULL, "<input>", "Binary to run");
cmd_run_argtable[5] = end = arg_end(10);
if (arg_nullcheck(cmd_run_argtable) != 0) {
fprintf(stderr, "insufficient memory\n");
return BLISP_ERR_OUT_OF_MEMORY;
}
return BLISP_OK;
}
void cmd_run_args_print_glossary() {
fputs("Usage: blisp", stdout);
arg_print_syntax(stdout, cmd_run_argtable, "\n");
puts("Flashes firmware to RAM and then executes it.");
arg_print_glossary(stdout, cmd_run_argtable, " %-25s %s\n");
}
blisp_return_t blisp_run_firmware() {
struct blisp_device device;
blisp_return_t ret;
ret = blisp_common_init_device(&device, port_name, chip_type);
if (ret != BLISP_OK) {
return ret;
}
FILE* data_file = fopen(binary_to_run->filename[0], "rb");
if (data_file == NULL) {
fprintf(stderr, "Failed to open data file \"%s\".\n",
binary_to_run->filename[0]);
ret = BLISP_ERR_CANT_OPEN_FILE;
goto exit1;
}
if (blisp_common_prepare_flash(&device, false) != 0) {
// TODO: Error handling
goto exit1;
}
struct blisp_easy_transport firmware_transport =
blisp_easy_transport_new_from_file(data_file);
ret = blisp_easy_load_ram_app(&device, &firmware_transport,
blisp_common_progress_callback);
if (ret != BLISP_OK) {
fprintf(stderr, "Failed to load firmware, ret: %d\n", ret);
goto exit1;
}
ret = blisp_device_check_image(&device);
if (ret != 0) {
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.\n");
goto exit1;
}
exit2:
if (data_file != NULL)
fclose(data_file);
exit1:
blisp_device_close(&device);
return ret;
}
blisp_return_t cmd_run_parse_exec(int argc, char** argv) {
int errors = arg_parse(argc, argv, cmd_run_argtable);
if (errors == 0) {
blisp_run_firmware();
return BLISP_OK;
} else if (cmd->count == 1) {
cmd_run_args_print_glossary();
return BLISP_OK;
}
return BLISP_ERR_INVALID_COMMAND;
}
void cmd_run_args_print_syntax() {
arg_print_syntax(stdout, cmd_run_argtable, "\n");
}
void cmd_run_free() {
arg_freetable(cmd_run_argtable,
sizeof(cmd_run_argtable) / sizeof(cmd_run_argtable[0]));
}
struct cmd cmd_run = {"run", cmd_run_args_init, cmd_run_parse_exec,
cmd_run_args_print_syntax, cmd_run_free};
+21 -54
View File
@@ -17,11 +17,9 @@
static struct arg_rex* cmd; static struct arg_rex* cmd;
static struct arg_file* binary_to_write; static struct arg_file* binary_to_write;
static struct arg_str *port_name, *chip_type; static struct arg_str *port_name, *chip_type;
static struct arg_int *baudrate;
static struct arg_lit* reset; static struct arg_lit* reset;
static struct arg_end* end; 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) { void fill_up_boot_header(struct bfl_boot_header* boot_header) {
memcpy(boot_header->magiccode, "BFNP", 4); memcpy(boot_header->magiccode, "BFNP", 4);
@@ -167,47 +165,23 @@ void fill_up_boot_header(struct bfl_boot_header* boot_header) {
boot_header->crc32 = 0xDEADBEEF; boot_header->crc32 = 0xDEADBEEF;
} }
blisp_return_t blisp_flash_firmware(void) { blisp_return_t blisp_flash_firmware() {
struct blisp_device device; struct blisp_device device;
blisp_return_t ret = BLISP_OK; blisp_return_t ret;
ret = blisp_common_init_device(&device, port_name, chip_type);
uint32_t baud = DEFAULT_BAUDRATE; if (ret != 0) {
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(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;
}
ret = blisp_common_init_device(&device, port_name, chip_type, baud);
if (ret != BLISP_OK) {
return ret; return ret;
} }
ret = blisp_common_prepare_flash(&device); if (blisp_common_prepare_flash(&device, true) != 0) {
if (ret != BLISP_OK) {
// TODO: Error handling // TODO: Error handling
goto exit1; goto exit1;
} }
parsed_firmware_file_t parsed_file; parsed_firmware_file_t parsed_file;
memset(&parsed_file, 0, sizeof(parsed_file)); memset(&parsed_file, 0, sizeof(parsed_file));
if (parse_firmware_file(binary_to_write->filename[0], &parsed_file) < 0) { int parsed_result =
// `parse_firmware_file` doesn't return `blisp_return_t` parse_firmware_file(binary_to_write->filename[0], &parsed_file);
// so we default to the generic error.
ret = BLISP_ERR_UNKNOWN;
goto exit1;
}
// If we are injecting a bootloader section, make it, erase flash, and flash // 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 // it. Then when we do firmware later on; it will be located afterwards
@@ -248,13 +222,13 @@ blisp_return_t blisp_flash_firmware(void) {
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
fprintf(stderr, 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%08X to 0x%08X\n",
parsed_file.payload_address, parsed_file.payload_address,
parsed_file.payload_address + parsed_file.payload_length + 1); parsed_file.payload_address + parsed_file.payload_length + 1);
goto exit2; goto exit2;
} }
printf("Flashing the firmware %zu bytes @ 0x%08zx...\n", printf("Flashing the firmware %d bytes @ 0x%08X...\n",
parsed_file.payload_length, parsed_file.payload_address); parsed_file.payload_length, parsed_file.payload_address);
struct blisp_easy_transport data_transport = struct blisp_easy_transport data_transport =
blisp_easy_transport_new_from_memory(parsed_file.payload, blisp_easy_transport_new_from_memory(parsed_file.payload,
@@ -264,7 +238,7 @@ blisp_return_t blisp_flash_firmware(void) {
&device, &data_transport, parsed_file.payload_address, &device, &data_transport, parsed_file.payload_address,
parsed_file.payload_length, blisp_common_progress_callback); 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"); fprintf(stderr, "Failed to write app to flash.\n");
goto exit2; goto exit2;
} }
@@ -290,28 +264,21 @@ exit2:
free(parsed_file.payload); free(parsed_file.payload);
exit1: exit1:
blisp_device_close(&device); blisp_device_close(&device);
return ret;
} }
blisp_return_t cmd_write_args_init(void) { blisp_return_t cmd_write_args_init() {
size_t index = 0; cmd_write_argtable[0] = cmd =
cmd_write_argtable[index++] = cmd =
arg_rex1(NULL, NULL, "write", NULL, REG_ICASE, NULL); 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"); 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>", arg_str0("p", "port", "<port_name>",
"Name/Path to the Serial Port (empty for search)"); "Name/Path to the Serial Port (empty for search)");
cmd_write_argtable[index++] = baudrate = cmd_write_argtable[3] = reset =
arg_int0("b", "baudrate", "<baud rate>",
"Serial baud rate (default: " XSTR(DEFAULT_BAUDRATE) ")");
cmd_write_argtable[index++] = reset =
arg_lit0(NULL, "reset", "Reset chip after write"); 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"); 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) { if (arg_nullcheck(cmd_write_argtable) != 0) {
fprintf(stderr, "insufficient memory\n"); fprintf(stderr, "insufficient memory\n");
@@ -320,7 +287,7 @@ blisp_return_t cmd_write_args_init(void) {
return BLISP_OK; return BLISP_OK;
} }
void cmd_write_args_print_glossary(void) { void cmd_write_args_print_glossary() {
fputs("Usage: blisp", stdout); fputs("Usage: blisp", stdout);
arg_print_syntax(stdout, cmd_write_argtable, "\n"); arg_print_syntax(stdout, cmd_write_argtable, "\n");
puts("Writes firmware to SPI Flash"); puts("Writes firmware to SPI Flash");
@@ -339,11 +306,11 @@ blisp_return_t cmd_write_parse_exec(int argc, char** argv) {
return BLISP_ERR_INVALID_COMMAND; 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"); arg_print_syntax(stdout, cmd_write_argtable, "\n");
} }
void cmd_write_free(void) { void cmd_write_free() {
arg_freetable(cmd_write_argtable, arg_freetable(cmd_write_argtable,
sizeof(cmd_write_argtable) / sizeof(cmd_write_argtable[0])); sizeof(cmd_write_argtable) / sizeof(cmd_write_argtable[0]));
} }
+31 -86
View File
@@ -8,7 +8,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "blisp_easy.h" #include "blisp_easy.h"
#include "blisp_util.h"
#include "error_codes.h" #include "error_codes.h"
#include "util.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, blisp_return_t blisp_common_init_device(struct blisp_device* device,
struct arg_str* port_name, struct arg_str* port_name,
struct arg_str* chip_type, struct arg_str* chip_type) {
uint32_t baudrate) {
if (chip_type->count == 0) { if (chip_type->count == 0) {
fprintf(stderr, "Chip type is invalid.\n"); fprintf(stderr, "Chip type is invalid.\n");
return BLISP_ERR_INVALID_CHIP_TYPE; 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; chip = &blisp_chip_bl70x;
} else if (strcmp(chip_type->sval[0], "bl60x") == 0) { } else if (strcmp(chip_type->sval[0], "bl60x") == 0) {
chip = &blisp_chip_bl60x; chip = &blisp_chip_bl60x;
} else if (strcmp(chip_type->sval[0], "bl808") == 0) {
chip = &blisp_chip_bl808;
} else { } else {
fprintf(stderr, "Chip type is invalid.\n"); fprintf(stderr, "Chip type is invalid.\n");
return BLISP_ERR_INVALID_CHIP_TYPE; 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; blisp_return_t ret;
ret = blisp_device_init(device, chip); ret = blisp_device_init(device, chip);
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
fprintf(stderr, "Failed to init device, ret: %d\n", ret); fprintf(stderr, "Failed to init device.\n");
return ret; return ret;
} }
ret = blisp_device_open(device, ret = blisp_device_open(device,
port_name->count == 1 ? port_name->sval[0] : NULL, port_name->count == 1 ? port_name->sval[0] : NULL);
baudrate);
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
if (ret == BLISP_ERR_DEVICE_NOT_FOUND) { fprintf(stderr, ret == BLISP_ERR_DEVICE_NOT_FOUND
fprintf(stderr, "Device not found\n"); ? "Device not found\n"
} else { : "Failed to open device.\n");
fprintf(stderr, "Failed to open device, ret: %d\n", ret);
}
return ret; return ret;
} }
@@ -65,82 +58,34 @@ blisp_return_t blisp_common_init_device(struct blisp_device* device,
* Prepares chip to access flash * Prepares chip to access flash
* this means performing handshake, and loading eflash_loader if needed. * this means performing handshake, and loading eflash_loader if needed.
*/ */
blisp_return_t blisp_common_prepare_flash(struct blisp_device* device) { blisp_return_t blisp_common_prepare_flash(struct blisp_device* device,
bool goto_eflash_loader) {
blisp_return_t ret = 0; 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; 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); ret = blisp_device_get_boot_info(device, &boot_info);
device->serial_timeout = previous_timeout; if (ret != BLISP_OK) {
fprintf(stderr, "Failed to get boot info.\n");
if (ret == BLISP_OK) { return ret;
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;
}
} }
// TODO: Do we want this to print in big endian to match the output printf(
// of Bouffalo's software? "BootROM version %d.%d.%d.%d, ChipID: "
if (device->chip->type == BLISP_CHIP_BL70X) { "%02X%02X%02X%02X%02X%02X%02X%02X\n",
printf( boot_info.boot_rom_version[0], boot_info.boot_rom_version[1],
"BootROM version %d.%d.%d.%d, ChipID: " boot_info.boot_rom_version[2], boot_info.boot_rom_version[3],
"%02X%02X%02X%02X%02X%02X%02X%02X\n", boot_info.chip_id[0], boot_info.chip_id[1], boot_info.chip_id[2],
boot_info.boot_rom_version[0], boot_info.boot_rom_version[1], boot_info.chip_id[3], boot_info.chip_id[4], boot_info.chip_id[5],
boot_info.boot_rom_version[2], boot_info.boot_rom_version[3], boot_info.chip_id[6], boot_info.chip_id[7]);
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) { if (device->chip->load_eflash_loader == NULL || !goto_eflash_loader) {
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;
}
}
if (device->chip->load_eflash_loader == NULL) {
return BLISP_OK; return BLISP_OK;
} }
@@ -175,20 +120,20 @@ blisp_return_t blisp_common_prepare_flash(struct blisp_device* device) {
ret = blisp_device_check_image(device); ret = blisp_device_check_image(device);
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "Failed to check image, ret: %d\n", ret); fprintf(stderr, "Failed to check image.\n");
goto exit1; goto exit1;
} }
ret = blisp_device_run_image(device); ret = blisp_device_run_image(device);
if (ret != BLISP_OK) { if (ret != BLISP_OK) {
fprintf(stderr, "Failed to run image, ret: %d\n", ret); fprintf(stderr, "Failed to run image.\n");
goto exit1; goto exit1;
} }
printf("Sending a handshake...\n"); printf("Sending a handshake...\n");
ret = blisp_device_handshake(device, true); ret = blisp_device_handshake(device, true);
if (ret != BLISP_OK) { 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; goto exit1;
} }
printf("Handshake with eflash_loader successful.\n"); printf("Handshake with eflash_loader successful.\n");
+3 -7
View File
@@ -6,13 +6,9 @@
#include <blisp.h> #include <blisp.h>
#include <argtable3.h> #include <argtable3.h>
// https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html blisp_return_t blisp_common_prepare_flash(struct blisp_device* device,
#define DEFAULT_BAUDRATE 460800 bool goto_eflash_loader);
#define STR(x) #x
#define XSTR(x) STR(x)
blisp_return_t blisp_common_prepare_flash(struct blisp_device* device);
void blisp_common_progress_callback(uint32_t current_value, uint32_t max_value); 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 #endif // BLISP_COMMON_H
@@ -1,7 +1,6 @@
list(APPEND ADD_INCLUDE list(APPEND ADD_INCLUDE
"${CMAKE_CURRENT_SOURCE_DIR}/bin" "${CMAKE_CURRENT_SOURCE_DIR}/bin"
"${CMAKE_CURRENT_SOURCE_DIR}/dfu" "${CMAKE_CURRENT_SOURCE_DIR}/dfu"
"${CMAKE_CURRENT_SOURCE_DIR}/hex"
"${CMAKE_CURRENT_SOURCE_DIR}" "${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}/bin/bin_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_file.c" "${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dfu/dfu_crc.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}/parse_file.c"
"${CMAKE_CURRENT_SOURCE_DIR}/get_file_contents.c" "${CMAKE_CURRENT_SOURCE_DIR}/get_file_contents.c"
) )
@@ -21,7 +19,6 @@ add_library(file_parsers STATIC
target_include_directories(file_parsers PUBLIC target_include_directories(file_parsers PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/bin ${CMAKE_CURRENT_SOURCE_DIR}/bin
${CMAKE_CURRENT_SOURCE_DIR}/dfu ${CMAKE_CURRENT_SOURCE_DIR}/dfu
${CMAKE_CURRENT_SOURCE_DIR}/hex
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
) )
@@ -78,7 +78,6 @@ int dfu_file_parse(const char* file_path_on_disk,
size_t* payload_address) { size_t* payload_address) {
uint8_t* dfu_file_contents = NULL; uint8_t* dfu_file_contents = NULL;
ssize_t file_size = get_file_contents(file_path_on_disk, &dfu_file_contents); 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) { if (file_size < 0) {
return file_size; 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 target_link_libraries(dfu_file_test
PRIVATE PRIVATE
GTest::GTest GTest::GTest
) )
include(GoogleTest) include_directories(dfu_file_test PRIVATE ../)
include_directories(dfu_file_test PRIVATE ../ ../../) add_test(dfu_file_test_gtests dfu_file_test)
target_compile_definitions(dfu_file_test PUBLIC "SOURCE_DIR=\"${CMAKE_SOURCE_DIR}\"")
gtest_discover_tests(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. // Created by ralim on 26/09/22.
// //
#include <gtest/gtest.h> #include "Config.h"
#include "dfu_file.h" #include "dfu_file.h"
#include <gtest/gtest.h>
TEST(DFU_FILE_PARSER, ParseTestFile) { TEST(DFU_FILE_PARSER, ParseTestFile) {
uint8_t* payload = nullptr; uint8_t* payload = nullptr;
size_t payload_size = 0; size_t payload_size = 0;
size_t payload_address = 0; size_t payload_address = 0;
int res = dfu_file_parse(SOURCE_DIR int res = dfu_file_parse(SOURCE_DIR "/test.dfu", &payload, &payload_size,
"/tools/blisp/src/file_parsers/dfu/tests/test.dfu", &payload_address);
&payload, &payload_size, &payload_address); ASSERT_EQ(res, 1);
ASSERT_EQ(res, 1); ASSERT_EQ(payload_size, 1337);
ASSERT_EQ(payload_size, 1337); ASSERT_EQ(payload_address, 0x11223344);
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
}
+1 -7
View File
@@ -2,7 +2,6 @@
#include <string.h> #include <string.h>
#include "bin_file.h" #include "bin_file.h"
#include "dfu_file.h" #include "dfu_file.h"
#include "hex_file.h"
const char* get_filename_ext(const char* filename) { const char* get_filename_ext(const char* filename) {
const char* dot = strrchr(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, res = bin_file_parse(file_path_on_disk, &parsed_results->payload,
&parsed_results->payload_length, &parsed_results->payload_length,
&parsed_results->payload_address); &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 // Normalise address, some builds will base the firmware at flash start but
// for the flasher we use 0 base (i.e. offsets into flash) // for the flasher we use 0 base (i.e. offsets into flash)
@@ -2,7 +2,6 @@
#define PARSE_FILE_H_ #define PARSE_FILE_H_
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> /* ssize_t */
#if defined(_MSC_VER) #if defined(_MSC_VER)
#include <BaseTsd.h> #include <BaseTsd.h>
typedef SSIZE_T ssize_t; typedef SSIZE_T ssize_t;
+2 -2
View File
@@ -5,7 +5,7 @@
#include "argtable3.h" #include "argtable3.h"
#include "cmd.h" #include "cmd.h"
struct cmd* cmds[] = {&cmd_write, &cmd_iot}; struct cmd* cmds[] = {&cmd_write, &cmd_run, &cmd_iot};
static uint8_t cmds_count = sizeof(cmds) / sizeof(cmds[0]); static uint8_t cmds_count = sizeof(cmds) / sizeof(cmds[0]);
@@ -45,7 +45,7 @@ int8_t args_parse_exec(int argc, char** argv) {
print_help(); print_help();
return BLISP_OK; return BLISP_OK;
} else if (version->count) { } 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"); printf("Copyright (C) 2023 Marek Kraus and PINE64 Community\n");
return BLISP_OK; return BLISP_OK;
} }
-1
View File
@@ -10,7 +10,6 @@
// to free an allocated buffer on the caller.nn // to free an allocated buffer on the caller.nn
#include <stdlib.h> #include <stdlib.h>
#include <mach-o/dyld.h>
static void util_get_executable_path(char* buffer_out, uint32_t max_size) { 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. assert(max_size >= PATH_MAX); // n.b. 1024 on MacOS. 4K on most Linux.