Author SHA1 Message Date
Terence Noone 6cece6970b Merge 5634b678f3 into d51e7bcc1e 2024-12-02 17:34:40 -06:00
Dom Rodriguez d51e7bcc1e fix: Fix mismatching format strings when writing
We were using the incorrect format string - this commit fixes that.

Signed-off-by: Dom Rodriguez <shymega@shymega.org.uk>
2024-12-02 09:27:13 +01:00
Dom Rodriguez d63612c256 fix: Make blisp check for existing file before flashing
This commit adds a simple check to both blisp commands that checks the
passed firmware .bin file exists, and is readable.

Justification: I flashed my Pinecil V2 that arrived today, and
misspelled the filename. blisp erased flash, and then exited - it did
not check the firmware .bin was readable/accessible, which meant my
Pinecil was soft-bricked.

I have tested the change, and it works for both commands when the input
file isn't readable.

I had to declare the `cmd_{iot,write}_args_print_glossary` function as
static before the call, so that we don't use undeclared functions before
we call them.

Signed-off-by: Dom Rodriguez <shymega@shymega.org.uk>
2024-12-01 16:44:17 +01:00
Dom Rodriguez 98784b1776 feat: Add Nix CI workflow
Signed-off-by: Dom Rodriguez <shymega@shymega.org.uk>
2024-12-01 16:43:49 +01:00
Dom Rodriguez 3490c37581 feat: Add Nix flake & derivation
This adds a Nix flake, shims for 'legacy' Nix, and a `.envrc` for
`direnv`. blisp is now able to run directly via:

`nix run github:pine64/blisp`

and for Nix/NixOS users, this helps with a one-click developer
environment.

Signed-off-by: Dom Rodriguez <shymega@shymega.org.uk>
2024-12-01 16:43:49 +01:00
Terence Noone 5634b678f3 Fix linking with argtable3
CMake interpreted `argtable3` to mean add `-largtable3` rather than to
use the imported argtable3 target. This worked when using the bundled
library, but broke with native libraries.
2024-03-03 00:46:22 -05:00
Terence Noone 8dbb58353b Do not build for both arm64 and x86_84 on macOS.
While this might work when using bundled libraries, this breaks with
system libraries as they are all compiled for arm64. Also, why would you
need to compile an x86_64 version on arm64, and vise versa.
2024-03-03 00:41:37 -05:00
Terence Noone f1fcdb9587 Use new find module for libserialport
This new find module will replace the old logic used to locate a native
copy of libserialport. THe old code didn't work on macOS, and was pretty
messy.
2024-03-03 00:41:29 -05:00
20 changed files with 284 additions and 154 deletions
+1
View File
@@ -0,0 +1 @@
use flake .
+16
View File
@@ -2,6 +2,22 @@ name: Build
on: [push, pull_request]
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:
runs-on: windows-2022
defaults:
-3
View File
@@ -1,7 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>
+6 -6
View File
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.16)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
project(blisp C)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 11)
@@ -42,11 +43,10 @@ set_target_properties(libblisp_static PROPERTIES
OUTPUT_NAME "blisp")
if(BLISP_USE_SYSTEM_LIBRARIES)
find_package(PkgConfig)
pkg_search_module(LIBSERIALPORT REQUIRED libserialport)
target_link_libraries(libblisp PUBLIC ${LIBSERIALPORT_LIBRARIES})
target_link_libraries(libblisp_static PUBLIC ${LIBSERIALPORT_LIBRARIES})
target_include_directories(libblisp_obj PUBLIC ${LIBSERIALPORT_INCLUDE_DIRS})
find_package(Libserialport REQUIRED)
target_link_libraries(libblisp PUBLIC Libserialport::Libserialport)
target_link_libraries(libblisp_static PUBLIC Libserialport::Libserialport)
target_include_directories(libblisp_obj PUBLIC ${Libserialport_INCLUDE_DIRS})
else()
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
target_sources(libblisp_obj PRIVATE
+49
View File
@@ -0,0 +1,49 @@
{
lib,
self,
stdenv,
fetchFromGitHub,
argtable,
cmake,
libserialport,
pkg-config,
testers,
IOKit ? null,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "blisp";
version = "0.0.4-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
@@ -0,0 +1,79 @@
# 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
@@ -0,0 +1,9 @@
(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
@@ -0,0 +1,27 @@
{
"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
@@ -0,0 +1,44 @@
{
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 ];
};
}
);
};
}
+1 -4
View File
@@ -8,10 +8,7 @@
struct blisp_easy_transport {
uint8_t type; // 0 - memory, 1 - FILE file_handle
union {
struct {
FILE* file_handle;
int64_t file_size;
} file;
FILE* file_handle;
struct {
void* data_location;
uint32_t data_size;
+5 -9
View File
@@ -19,7 +19,7 @@ static blisp_return_t blisp_easy_transport_read(
transport->data.memory.current_position += size;
return size;
} else {
return fread(buffer, size, 1, transport->data.file.file_handle);
return fread(buffer, size, 1, transport->data.file_handle);
}
}
@@ -28,13 +28,9 @@ static blisp_return_t blisp_easy_transport_size(
if (transport->type == 0) {
return transport->data.memory.data_size;
} else {
if (transport->data.file.file_size == -1) {
FILE* handle = transport->data.file.file_handle;
fseek(handle, 0, SEEK_END);
transport->data.file.file_size = ftell(handle);
rewind(handle);
}
return transport->data.file.file_size;
// TODO: Implement
printf("%s() Warning: calling non-implemented function\n", __func__);
return BLISP_ERR_NOT_IMPLEMENTED;
}
}
@@ -47,7 +43,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 transport = {.type = 1, .data.file.file_handle = file, .data.file.file_size = -1};
struct blisp_easy_transport transport = {.type = 1, .data.file_handle = file};
return transport;
}
+9
View File
@@ -0,0 +1,9 @@
(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 -2
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_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 src/cmd/run.c)
add_executable(blisp src/main.c src/cmd/write.c src/util.c src/common.c src/cmd/iot.c)
add_subdirectory(src/file_parsers)
@@ -20,7 +20,7 @@ target_include_directories(blisp PRIVATE
"${CMAKE_SOURCE_DIR}/include")
target_link_libraries(blisp PRIVATE
argtable3
argtable3::argtable3
libblisp_static file_parsers)
if (WIN32)
+8 -1
View File
@@ -2,6 +2,14 @@
#ifndef 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 "error_codes.h"
struct cmd {
@@ -13,7 +21,6 @@ struct cmd {
};
extern struct cmd cmd_write;
extern struct cmd cmd_run;
extern struct cmd cmd_iot;
#endif // BLISP_CMD_H
+10 -1
View File
@@ -13,16 +13,25 @@ static struct arg_str *port_name, *chip_type; // TODO: Make this common
static struct arg_lit* reset;
static struct arg_end* end;
static void* cmd_iot_argtable[7];
static void cmd_iot_args_print_glossary();
blisp_return_t blisp_single_download() {
struct blisp_device device;
blisp_return_t ret;
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);
if (ret != BLISP_OK) {
return ret;
}
ret = blisp_common_prepare_flash(&device, true);
ret = blisp_common_prepare_flash(&device);
if (ret != BLISP_OK) {
// TODO: Error handling
goto exit1;
-119
View File
@@ -1,119 +0,0 @@
#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};
+14 -3
View File
@@ -20,6 +20,7 @@ static struct arg_str *port_name, *chip_type;
static struct arg_lit* reset;
static struct arg_end* end;
static void* cmd_write_argtable[6];
static void cmd_write_args_print_glossary();
void fill_up_boot_header(struct bfl_boot_header* boot_header) {
memcpy(boot_header->magiccode, "BFNP", 4);
@@ -168,16 +169,26 @@ void fill_up_boot_header(struct bfl_boot_header* boot_header) {
blisp_return_t blisp_flash_firmware() {
struct blisp_device device;
blisp_return_t ret;
if (access(binary_to_write->filename[0], R_OK) != 0) {
// File not accessible, error out.
fprintf(stderr, "Input firmware not found: %s\n", binary_to_write->filename[0]);
cmd_write_args_print_glossary(); /* Print help to assist user */
/* No need to free memory, will now exit with ret code 1 */
return 1;
}
ret = blisp_common_init_device(&device, port_name, chip_type);
if (ret != 0) {
return ret;
}
if (blisp_common_prepare_flash(&device, true) != 0) {
if (blisp_common_prepare_flash(&device) != 0) {
// TODO: Error handling
goto exit1;
}
parsed_firmware_file_t parsed_file;
memset(&parsed_file, 0, sizeof(parsed_file));
int parsed_result =
@@ -222,13 +233,13 @@ blisp_return_t blisp_flash_firmware() {
if (ret != BLISP_OK) {
fprintf(stderr,
"Failed to erase flash. Tried to erase from 0x%08X to 0x%08X\n",
"Failed to erase flash. Tried to erase from 0x%08lu to 0x%08lu\n",
parsed_file.payload_address,
parsed_file.payload_address + parsed_file.payload_length + 1);
goto exit2;
}
printf("Flashing the firmware %d bytes @ 0x%08X...\n",
printf("Flashing the firmware %lu bytes @ 0x%08lu...\n",
parsed_file.payload_length, parsed_file.payload_address);
struct blisp_easy_transport data_transport =
blisp_easy_transport_new_from_memory(parsed_file.payload,
+2 -3
View File
@@ -58,8 +58,7 @@ blisp_return_t blisp_common_init_device(struct blisp_device* device,
* Prepares chip to access flash
* this means performing handshake, and loading eflash_loader if needed.
*/
blisp_return_t blisp_common_prepare_flash(struct blisp_device* device,
bool goto_eflash_loader) {
blisp_return_t blisp_common_prepare_flash(struct blisp_device* device) {
blisp_return_t ret = 0;
printf("Sending a handshake...\n");
@@ -85,7 +84,7 @@ blisp_return_t blisp_common_prepare_flash(struct blisp_device* device,
boot_info.chip_id[3], boot_info.chip_id[4], boot_info.chip_id[5],
boot_info.chip_id[6], boot_info.chip_id[7]);
if (device->chip->load_eflash_loader == NULL || !goto_eflash_loader) {
if (device->chip->load_eflash_loader == NULL) {
return BLISP_OK;
}
+1 -2
View File
@@ -6,8 +6,7 @@
#include <blisp.h>
#include <argtable3.h>
blisp_return_t blisp_common_prepare_flash(struct blisp_device* device,
bool goto_eflash_loader);
int32_t blisp_common_prepare_flash(struct blisp_device* device);
void blisp_common_progress_callback(uint32_t current_value, uint32_t max_value);
int32_t blisp_common_init_device(struct blisp_device* device, struct arg_str* port_name, struct arg_str* chip_type);
+1 -1
View File
@@ -5,7 +5,7 @@
#include "argtable3.h"
#include "cmd.h"
struct cmd* cmds[] = {&cmd_write, &cmd_run, &cmd_iot};
struct cmd* cmds[] = {&cmd_write, &cmd_iot};
static uint8_t cmds_count = sizeof(cmds) / sizeof(cmds[0]);