From 877b4bd2af2a1e418dcc1df48ae3f14ad71c5f67 Mon Sep 17 00:00:00 2001 From: Ruslan Migirov Date: Fri, 5 Jun 2026 21:12:02 +0300 Subject: [PATCH 1/2] Support AVR32 builds on macOS --- makefile.defs | 21 +++++++++++++++++++++ src/newlib_compat.c | 5 +++++ 2 files changed, 26 insertions(+) create mode 100644 makefile.defs create mode 100644 src/newlib_compat.c diff --git a/makefile.defs b/makefile.defs new file mode 100644 index 00000000..9d9bb36f --- /dev/null +++ b/makefile.defs @@ -0,0 +1,21 @@ +# +# Local build settings. This file is included by Release/makefile. +# +AVR32_TOOLCHAIN ?= + +ifeq ($(strip $(ATMEL_HEADERS)),) +ifneq ($(strip $(AVR32_TOOLCHAIN)),) +ATMEL_HEADERS := $(firstword $(wildcard $(AVR32_TOOLCHAIN)/atmel-headers/atmel-headers-*)) +endif +endif + +ifneq ($(strip $(ATMEL_HEADERS)),) +CFLAGS += -I$(ATMEL_HEADERS) +ASFLAGS += -I$(ATMEL_HEADERS) +endif + +OBJS += ./src/newlib_compat.o + +src/newlib_compat.o: ../src/newlib_compat.c + @echo Compile $(CFLAGS) $< + @avr32-gcc $(CFLAGS) -O2 -fdata-sections -Wall -c -fmessage-length=0 -ffunction-sections -o"$@" "$<" diff --git a/src/newlib_compat.c b/src/newlib_compat.c new file mode 100644 index 00000000..a6bdd2d1 --- /dev/null +++ b/src/newlib_compat.c @@ -0,0 +1,5 @@ +int _isatty(int file) +{ + (void) file; + return 0; +} From 6b204b79a7d164f7c5b2627fea15f98d26aa91c1 Mon Sep 17 00:00:00 2001 From: Ruslan Migirov Date: Mon, 8 Jun 2026 01:47:50 +0300 Subject: [PATCH 2/2] Add macOS AVR32 firmware CI --- .github/workflows/avr32-build.yml | 60 +++++++++++++++++++++++++++++++ Makefile | 9 ++++- makefile.defs | 3 +- src/newlib_compat.c | 4 +-- widget-control.c | 22 ++++++++---- 5 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/avr32-build.yml diff --git a/.github/workflows/avr32-build.yml b/.github/workflows/avr32-build.yml new file mode 100644 index 00000000..17d79caa --- /dev/null +++ b/.github/workflows/avr32-build.yml @@ -0,0 +1,60 @@ +name: AVR32 firmware build + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +env: + TOOLCHAIN_REPO: cozycactus/avr32-toolchain-macos-arm64 + TOOLCHAIN_TAG: v2026.06.03 + TOOLCHAIN_ARCHIVE: avr32-tools-src-macos-arm64-20260603.tar.gz + ATMEL_HEADERS_VERSION: 6.1.3.1475 + +jobs: + avr32: + name: Build SDR Widget with avr32-gcc + runs-on: macos-26 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Install host dependencies + run: brew install libusb + + - name: Download AVR32 toolchain + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release download "$TOOLCHAIN_TAG" \ + --repo "$TOOLCHAIN_REPO" \ + --pattern "$TOOLCHAIN_ARCHIVE" \ + --pattern "$TOOLCHAIN_ARCHIVE.sha256" + expected="$(awk '{print $1}' "$TOOLCHAIN_ARCHIVE.sha256")" + actual="$(shasum -a 256 "$TOOLCHAIN_ARCHIVE" | awk '{print $1}')" + test "$actual" = "$expected" + mkdir -p toolchain + tar -xzf "$TOOLCHAIN_ARCHIVE" -C toolchain + + - name: Download Atmel headers + run: | + toolchain_root="$PWD/toolchain/avr32-tools-src" + headers_zip="atmel-headers-${ATMEL_HEADERS_VERSION}.zip" + mkdir -p "$toolchain_root/downloads" "$toolchain_root/atmel-headers" + curl -L \ + "https://ww1.microchip.com/downloads/archive/${headers_zip}" \ + -o "$toolchain_root/downloads/${headers_zip}" + unzip -q -o "$toolchain_root/downloads/${headers_zip}" \ + -d "$toolchain_root/atmel-headers" + + - name: Build firmware and host control tool + run: | + toolchain_root="$PWD/toolchain/avr32-tools-src" + export PATH="$toolchain_root/bin:$PATH" + avr32-gcc --version + make clean + make all AVR32_TOOLCHAIN="$toolchain_root" diff --git a/Makefile b/Makefile index 6be54d90..30329893 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,13 @@ ## ## assumes that you've set the AVR32BIN environment ## to point to the directory containing avr32-gcc +HOST_CC ?= gcc +PKG_CONFIG ?= pkg-config +LIBUSB_CFLAGS ?= $(shell $(PKG_CONFIG) --variable=includedir libusb-1.0 2>/dev/null | sed 's|^|-I|') +LIBUSB_LIBS ?= $(shell $(PKG_CONFIG) --libs libusb-1.0 2>/dev/null || echo -lusb-1.0) +HOST_CFLAGS ?= +HOST_LDFLAGS ?= + all:: Release/widget.elf widget-control Release/widget.elf:: @@ -19,7 +26,7 @@ sdr-widget:: CFLAGS=-DFEATURE_DEFAULT_BOARD=feature_board_widget ./make-widget widget-control: widget-control.c src/features.h - gcc -o widget-control widget-control.c -lusb-1.0 + $(HOST_CC) $(HOST_CFLAGS) $(LIBUSB_CFLAGS) -o widget-control widget-control.c $(HOST_LDFLAGS) $(LIBUSB_LIBS) clean:: cd Release && make clean diff --git a/makefile.defs b/makefile.defs index 9d9bb36f..3f852264 100644 --- a/makefile.defs +++ b/makefile.defs @@ -1,6 +1,4 @@ -# # Local build settings. This file is included by Release/makefile. -# AVR32_TOOLCHAIN ?= ifeq ($(strip $(ATMEL_HEADERS)),) @@ -12,6 +10,7 @@ endif ifneq ($(strip $(ATMEL_HEADERS)),) CFLAGS += -I$(ATMEL_HEADERS) ASFLAGS += -I$(ATMEL_HEADERS) +export CPATH := $(ATMEL_HEADERS):$(CPATH) endif OBJS += ./src/newlib_compat.o diff --git a/src/newlib_compat.c b/src/newlib_compat.c index a6bdd2d1..6c305f5e 100644 --- a/src/newlib_compat.c +++ b/src/newlib_compat.c @@ -1,5 +1,5 @@ int _isatty(int file) { - (void) file; - return 0; + (void)file; + return 0; } diff --git a/widget-control.c b/widget-control.c index 62b62f96..9970fc18 100644 --- a/widget-control.c +++ b/widget-control.c @@ -39,6 +39,8 @@ const char usage[] = { int verbose = 0; +int finish(int return_value); + /* ** features */ @@ -123,7 +125,7 @@ int find_feature_value(int index, char *value) { char *usb_serial_id = NULL; libusb_device_handle *usb_handle; char *usb_device = "none"; -char usb_data[1024]; +unsigned char usb_data[1024]; unsigned int usb_timeout = 2000; @@ -188,13 +190,15 @@ libusb_device_handle *find_device(int list_all) { libusb_close(h); continue; } - unsigned char serialId[1024]; - if ((status = libusb_get_string_descriptor_ascii(h, desc.iSerialNumber, serialId, sizeof(serialId))) <= 0) { - if (verbose) - if (status == 0) + char serialId[1024]; + if ((status = libusb_get_string_descriptor_ascii(h, desc.iSerialNumber, (unsigned char *)serialId, sizeof(serialId))) <= 0) { + if (verbose) { + if (status == 0) { fprintf(stderr, "find_device: libusb_get_string_descriptor_ascii(%04x:%04x, ...) returned 0 bytes", desc.idVendor, desc.idProduct); - else + } else { fprintf(stderr, "find_device: libusb_get_string_descriptor_ascii(%04x:%04x, ...) failed: %s", desc.idVendor, desc.idProduct, error_string(status)); + } + } libusb_release_interface(h, 0); libusb_close(h); continue; @@ -430,7 +434,11 @@ int set_nvram(int argc, char *argv[]) { fprintf(stderr, "widget-control: wrong number (%d) of features specified, should be %d features to set\n", argc, true_feature_end_index); exit(1); } - features = (uint8_t *)calloc(true_feature_major_index, sizeof(uint8_t)); + features = (uint8_t *)calloc(true_feature_end_index, sizeof(uint8_t)); + if (features == NULL) { + fprintf(stderr, "widget-control: unable to allocate feature values\n"); + exit(finish(1)); + } for (i = true_feature_minor_index+1; i < true_feature_end_index; i += 1) { j = find_feature_value(i, argv[i]); if (j >= first_value(i) && j <= last_value(i)) {