From b8b7d5a3e156e671f64573cad34286bea7b187b3 Mon Sep 17 00:00:00 2001 From: Tucker Kern Date: Thu, 18 Dec 2025 08:28:34 -0700 Subject: [PATCH 1/5] Attempt to remove bcm_host library dependency by replicating necessary code in bcm283x --- Makefile | 2 +- README.md | 4 - include/bcm283x/bcm283x.h | 10 +++ source/bcm283x/bcm283x.c | 157 ++++++++++++++++++++++++++++++++++++-- source/main.c | 7 +- 5 files changed, 166 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index e814ab7..94b787c 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ TARGET = $(BUILD_DIR)/$(TARGET_NAME) INC_DIRS := $(shell find $(INC_BASE) -type d) /opt/vc/include INC_FLAGS := $(addprefix -I ,$(INC_DIRS)) -LDFLAGS := -L /opt/vc/lib -lbcm_host -lm -lvcos -lpthread -lstdc++ +LDFLAGS := -L /opt/vc/lib -lm -lvcos -lpthread -lstdc++ CPPFLAGS ?= $(INC_FLAGS) -MMD CFLAGS ?= -Wall -Wno-missing-braces CC = clang diff --git a/README.md b/README.md index a26d279..4654254 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,6 @@ Install necessary packages ``` sudo apt-get install build-essential clang git ``` -Debian 12 (Bookworm) requires this additional depenency. -``` -sudo apt-get install libraspberrypi-dev -``` Just run make. No configuration right now. ``` diff --git a/include/bcm283x/bcm283x.h b/include/bcm283x/bcm283x.h index bd71209..401fce9 100644 --- a/include/bcm283x/bcm283x.h +++ b/include/bcm283x/bcm283x.h @@ -5,6 +5,12 @@ #include #include +#define BCM283X_PROCESSOR_BCM2835 0 +#define BCM283X_PROCESSOR_BCM2836 1 +#define BCM283X_PROCESSOR_BCM2837 2 +#define BCM283X_PROCESSOR_BCM2838 3 // Deprecated name +#define BCM283X_PROCESSOR_BCM2711 3 + // Enable GPIOs 32 - 54 // #define BCM283X_EXTENDED_GPIO @@ -19,6 +25,10 @@ void bcm283x_init(void); void bcm283x_delay_microseconds(uint32_t microseconds); +uintptr_t bcm283x_get_peripheral_address(void); +uintptr_t bcm283x_get_peripheral_size(void); +uintptr_t bcm283x_get_sdram_address(void); +bool bcm283x_is_model_pi4(void); #include "bcm283x_clock.h" #include "bcm283x_dma.h" diff --git a/source/bcm283x/bcm283x.c b/source/bcm283x/bcm283x.c index 605ea8f..091df5f 100644 --- a/source/bcm283x/bcm283x.c +++ b/source/bcm283x/bcm283x.c @@ -1,7 +1,7 @@ #include #include - -#include +#include +#include #include "bcm283x.h" #include "log.h" @@ -28,8 +28,8 @@ void bcm283x_init() } // Fetch physical address and length of peripherals for our system - off_t physical_base = bcm_host_get_peripheral_address(); - size_t length = bcm_host_get_peripheral_size(); + off_t physical_base = bcm283x_get_peripheral_address(); + size_t length = bcm283x_get_peripheral_size(); // Map to virtual memory virtual_base = memory_map_physical(physical_base, length); @@ -57,4 +57,151 @@ void bcm283x_init() void bcm283x_delay_microseconds(uint32_t microseconds) { microsleep(microseconds); -} \ No newline at end of file +} + +/** + @brief Fetch address information from the device tree + + @param filename Device tree node + @param offset Offset in node to read + @retval uintptr_t +*/ +static uintptr_t bcm283x_get_dt_ranges(const char* filename, off_t offset) +{ + // Open node + FILE* fp = fopen(filename, "rb"); + if (fp == NULL) + return UINTPTR_MAX; + + // Seek to offset + fseek(fp, offset, SEEK_SET); + + // Read range from node + uintptr_t address = UINTPTR_MAX; + unsigned char buffer[4]; + if (fread(buffer, 1, sizeof(buffer), fp) == sizeof(buffer)) + address = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3] << 0; + + // Cleanup + fclose(fp); + + return address; +} + +/** + @brief Get the peripheral base address from the device tree + + @param none + @retval uintptr_t +*/ +uintptr_t bcm283x_get_peripheral_address(void) +{ + uintptr_t address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); + if (address == 0) + address = get_dt_ranges("/proc/device-tree/soc/ranges", 8); + return address == UINTPTR_MAX ? 0x20000000 : address; +} + +/** + @brief Get the peripheral address size from the device tree + + @param none + @retval uintptr_t +*/ +uintptr_t bcm283x_get_peripheral_size(void) +{ + uintptr_t address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); + address = get_dt_ranges("/proc/device-tree/soc/ranges", (address == 0) ? 12 : 8); + return address == UINTPTR_MAX ? 0x01000000 : address; +} + +/** + @brief Get the physical address of the SDRAM from the device tree + + @param none + @retval uintptr_t +*/ +uintptr_t bcm283x_get_sdram_address(void) +{ + uintptr_t address = get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8); + return address == UINTPTR_MAX ? 0x40000000 : address; +} + +/** + @brief Read a string from the given file + + @param filename Filename to read + @param format String format to extract + @param value Storage for extracted value + @retval bool +*/ +static bool bcm283x_get_string_from_file(const char* filename, const char* format, uint32_t* value) +{ + // Open the file + FILE* file = fopen(filename, "rt"); + if (file == NULL) + return false; + + char str[256] = {0}; + bool found = false; + while (fgets(str, sizeof(str), file) != NULL) + { + if (sscanf(str, format, value) == 1) + { + found = true; + break; + } + } + + fclose(file); + + return found; +} + +/** + @brief Get the processor revision code + + @param none + @retval uint32_t +*/ +static uint32_t bcm283x_get_revision_code() +{ + static uint32_t revision_num = UINT32_MAX; + + if (revision_num != UINT32_MAX) + return revision_num; + + uint32_t num = UINT32_MAX; + if (read_string_from_file("/proc/cpuinfo", "Revision : %x", &num)) + revision_num = num; + + return revision_num; +} + +/** + @brief Get the processor ID + + @param none + @retval uint32_t +*/ +static uint32_t bcm283x_get_processor_id(void) +{ + uint32_t revision_num = bcm283x_get_revision_code(); + + if (revision_num & 0x800000) + return (revision_num & 0xf000) >> 12; + + // Old style number only used 2835 + return BCM283X_PROCESSOR_BCM2835; +} + +/** + @brief Check if the system is a Pi 4 + + @param none + @retval bool +*/ +bool bcm283x_is_model_pi4(void) +{ + return bcm283x_get_processor_id() == BCM283X_PROCESSOR_BCM2711; +} diff --git a/source/main.c b/source/main.c index 2c7e67c..9d1f7c1 100644 --- a/source/main.c +++ b/source/main.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -185,7 +184,7 @@ static void raspdif_init(dma_channel_t dma_channel, double sample_rate_hz) // Map the physical memory into our address space uint8_t* bus_base = (uint8_t*)(uintptr_t)memory.address; - uint8_t* physical_base = bus_base - bcm_host_get_sdram_address(); + uint8_t* physical_base = bus_base - bcm283x_get_sdram_address(); uint8_t* virtual_base = (uint8_t*)memory_map_physical((off_t)physical_base, sizeof(raspdif_control_t)); if (virtual_base == NULL) { @@ -218,7 +217,7 @@ static void raspdif_init(dma_channel_t dma_channel, double sample_rate_hz) double spdif_clock = sample_rate_hz * 64.0 * 2.0; LOGD(TAG, "Calculated SPDIF clock of %g Hz for sample rate of %g Hz.", spdif_clock, sample_rate_hz); - double pll_freq_hz = bcm_host_is_model_pi4() ? 750e6 : 500e6; + double pll_freq_hz = bcm283x_is_model_pi4() ? 750e6 : 500e6; double divisor = (pll_freq_hz / spdif_clock); double divi = 0; @@ -459,7 +458,7 @@ int main(int argc, char* argv[]) #endif // Initialize hardware and buffers - dma_channel_t dma_channel = bcm_host_is_model_pi4() ? dma_channel_5 : dma_channel_13; + dma_channel_t dma_channel = bcm283x_is_model_pi4() ? dma_channel_5 : dma_channel_13; raspdif_init(dma_channel, arguments.sample_rate); // Allocate storage for a SPDIF block From 61041aa71e461dcceb3e28b6c3e259d572603ae9 Mon Sep 17 00:00:00 2001 From: Tucker Kern Date: Fri, 19 Dec 2025 08:10:41 -0700 Subject: [PATCH 2/5] Fix old usage of get_dt_ranges --- source/bcm283x/bcm283x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/bcm283x/bcm283x.c b/source/bcm283x/bcm283x.c index 091df5f..829c079 100644 --- a/source/bcm283x/bcm283x.c +++ b/source/bcm283x/bcm283x.c @@ -96,9 +96,9 @@ static uintptr_t bcm283x_get_dt_ranges(const char* filename, off_t offset) */ uintptr_t bcm283x_get_peripheral_address(void) { - uintptr_t address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); + uintptr_t address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 4); if (address == 0) - address = get_dt_ranges("/proc/device-tree/soc/ranges", 8); + address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 8); return address == UINTPTR_MAX ? 0x20000000 : address; } @@ -110,8 +110,8 @@ uintptr_t bcm283x_get_peripheral_address(void) */ uintptr_t bcm283x_get_peripheral_size(void) { - uintptr_t address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); - address = get_dt_ranges("/proc/device-tree/soc/ranges", (address == 0) ? 12 : 8); + uintptr_t address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 4); + address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", (address == 0) ? 12 : 8); return address == UINTPTR_MAX ? 0x01000000 : address; } @@ -123,7 +123,7 @@ uintptr_t bcm283x_get_peripheral_size(void) */ uintptr_t bcm283x_get_sdram_address(void) { - uintptr_t address = get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8); + uintptr_t address = bcm283x_get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8); return address == UINTPTR_MAX ? 0x40000000 : address; } From 14acc94df5e82924a02eb4aedd4ee2c6178c6f1e Mon Sep 17 00:00:00 2001 From: Tucker Kern Date: Fri, 19 Dec 2025 08:11:05 -0700 Subject: [PATCH 3/5] Fix missing usage of bcm283x_get_string_from_file --- source/bcm283x/bcm283x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/bcm283x/bcm283x.c b/source/bcm283x/bcm283x.c index 829c079..e9da8fa 100644 --- a/source/bcm283x/bcm283x.c +++ b/source/bcm283x/bcm283x.c @@ -172,7 +172,7 @@ static uint32_t bcm283x_get_revision_code() return revision_num; uint32_t num = UINT32_MAX; - if (read_string_from_file("/proc/cpuinfo", "Revision : %x", &num)) + if (bcm283x_get_string_from_file("/proc/cpuinfo", "Revision : %x", &num)) revision_num = num; return revision_num; From 1230f3bbce3eedff35b87ec51e0e82ee93afa9ca Mon Sep 17 00:00:00 2001 From: Tucker Kern Date: Fri, 19 Dec 2025 08:13:18 -0700 Subject: [PATCH 4/5] Remove libvcos dependency --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 94b787c..762ac88 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ TARGET = $(BUILD_DIR)/$(TARGET_NAME) INC_DIRS := $(shell find $(INC_BASE) -type d) /opt/vc/include INC_FLAGS := $(addprefix -I ,$(INC_DIRS)) -LDFLAGS := -L /opt/vc/lib -lm -lvcos -lpthread -lstdc++ +LDFLAGS := -L /opt/vc/lib -lm -lpthread -lstdc++ CPPFLAGS ?= $(INC_FLAGS) -MMD CFLAGS ?= -Wall -Wno-missing-braces CC = clang From f667ca83f141b147d97d7464a2dce611074d6f83 Mon Sep 17 00:00:00 2001 From: Tucker Kern Date: Sat, 20 Dec 2025 13:10:21 -0700 Subject: [PATCH 5/5] Return peripheral addresses as 32bits wide and ensure addresses are logged at their full width when possible --- include/bcm283x/bcm283x.h | 6 +++--- source/bcm283x/bcm283x.c | 32 ++++++++++++++++---------------- source/memory.c | 8 ++++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/bcm283x/bcm283x.h b/include/bcm283x/bcm283x.h index 401fce9..1d1c4c5 100644 --- a/include/bcm283x/bcm283x.h +++ b/include/bcm283x/bcm283x.h @@ -25,9 +25,9 @@ void bcm283x_init(void); void bcm283x_delay_microseconds(uint32_t microseconds); -uintptr_t bcm283x_get_peripheral_address(void); -uintptr_t bcm283x_get_peripheral_size(void); -uintptr_t bcm283x_get_sdram_address(void); +uint32_t bcm283x_get_peripheral_address(void); +uint32_t bcm283x_get_peripheral_size(void); +uint32_t bcm283x_get_sdram_address(void); bool bcm283x_is_model_pi4(void); #include "bcm283x_clock.h" diff --git a/source/bcm283x/bcm283x.c b/source/bcm283x/bcm283x.c index e9da8fa..da1086a 100644 --- a/source/bcm283x/bcm283x.c +++ b/source/bcm283x/bcm283x.c @@ -64,20 +64,20 @@ void bcm283x_delay_microseconds(uint32_t microseconds) @param filename Device tree node @param offset Offset in node to read - @retval uintptr_t + @retval uint32_t */ -static uintptr_t bcm283x_get_dt_ranges(const char* filename, off_t offset) +static uint32_t bcm283x_get_dt_ranges(const char* filename, off_t offset) { // Open node FILE* fp = fopen(filename, "rb"); if (fp == NULL) - return UINTPTR_MAX; + return UINT32_MAX; // Seek to offset fseek(fp, offset, SEEK_SET); // Read range from node - uintptr_t address = UINTPTR_MAX; + uint32_t address = UINT32_MAX; unsigned char buffer[4]; if (fread(buffer, 1, sizeof(buffer), fp) == sizeof(buffer)) address = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3] << 0; @@ -92,39 +92,39 @@ static uintptr_t bcm283x_get_dt_ranges(const char* filename, off_t offset) @brief Get the peripheral base address from the device tree @param none - @retval uintptr_t + @retval uint32_t */ -uintptr_t bcm283x_get_peripheral_address(void) +uint32_t bcm283x_get_peripheral_address(void) { - uintptr_t address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 4); + uint32_t address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 4); if (address == 0) address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 8); - return address == UINTPTR_MAX ? 0x20000000 : address; + return address == UINT32_MAX ? 0x20000000 : address; } /** @brief Get the peripheral address size from the device tree @param none - @retval uintptr_t + @retval uint32_t */ -uintptr_t bcm283x_get_peripheral_size(void) +uint32_t bcm283x_get_peripheral_size(void) { - uintptr_t address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 4); + uint32_t address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", 4); address = bcm283x_get_dt_ranges("/proc/device-tree/soc/ranges", (address == 0) ? 12 : 8); - return address == UINTPTR_MAX ? 0x01000000 : address; + return address == UINT32_MAX ? 0x01000000 : address; } /** @brief Get the physical address of the SDRAM from the device tree @param none - @retval uintptr_t + @retval uint32_t */ -uintptr_t bcm283x_get_sdram_address(void) +uint32_t bcm283x_get_sdram_address(void) { - uintptr_t address = bcm283x_get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8); - return address == UINTPTR_MAX ? 0x40000000 : address; + uint32_t address = bcm283x_get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8); + return address == UINT32_MAX ? 0x40000000 : address; } /** diff --git a/source/memory.c b/source/memory.c index 5adff2e..65df8bd 100644 --- a/source/memory.c +++ b/source/memory.c @@ -30,7 +30,7 @@ void* memory_map_physical(off_t offset, size_t length) void* virtual = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, file, offset); if (virtual == MAP_FAILED) { - LOGF(TAG, "Failed to map physical address 0x%X of length %d. Error: %s", offset, length, strerror(errno)); + LOGF(TAG, "Failed to map physical address 0x%lX of length %d. Error: %s", offset, length, strerror(errno)); return NULL; } @@ -38,7 +38,7 @@ void* memory_map_physical(off_t offset, size_t length) if (result == -1) LOGE(TAG, "Failed to close /dev/mem. Error: %s", strerror(errno)); - LOGD(TAG, "Mapped physical address 0x%X to virtual address 0x%X", offset, virtual); + LOGD(TAG, "Mapped physical address 0x%lX to virtual address 0x%lX", offset, virtual); return virtual; } @@ -59,7 +59,7 @@ void* memory_allocate_virtual(size_t length) return NULL; } - LOGD(TAG, "Allocated virtual memory at 0x%X of length %d.", virtual, length); + LOGD(TAG, "Allocated virtual memory at 0x%lX of length %d.", virtual, length); return virtual; } @@ -93,7 +93,7 @@ memory_physical_t memory_allocate_physical(size_t length) return memory; } - LOGD(TAG, "Allocated memory at 0x%X of length %d.", memory.address, length); + LOGD(TAG, "Allocated memory at 0x%lX of length %d.", memory.address, length); return memory; }