diff --git a/Makefile b/Makefile index e814ab7..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 -lbcm_host -lm -lvcos -lpthread -lstdc++ +LDFLAGS := -L /opt/vc/lib -lm -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..1d1c4c5 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); +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" #include "bcm283x_dma.h" diff --git a/source/bcm283x/bcm283x.c b/source/bcm283x/bcm283x.c index 605ea8f..da1086a 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 uint32_t +*/ +static uint32_t bcm283x_get_dt_ranges(const char* filename, off_t offset) +{ + // Open node + FILE* fp = fopen(filename, "rb"); + if (fp == NULL) + return UINT32_MAX; + + // Seek to offset + fseek(fp, offset, SEEK_SET); + + // Read range from node + 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; + + // Cleanup + fclose(fp); + + return address; +} + +/** + @brief Get the peripheral base address from the device tree + + @param none + @retval uint32_t +*/ +uint32_t bcm283x_get_peripheral_address(void) +{ + 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 == UINT32_MAX ? 0x20000000 : address; +} + +/** + @brief Get the peripheral address size from the device tree + + @param none + @retval uint32_t +*/ +uint32_t bcm283x_get_peripheral_size(void) +{ + 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 == UINT32_MAX ? 0x01000000 : address; +} + +/** + @brief Get the physical address of the SDRAM from the device tree + + @param none + @retval uint32_t +*/ +uint32_t bcm283x_get_sdram_address(void) +{ + uint32_t address = bcm283x_get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8); + return address == UINT32_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 (bcm283x_get_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 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; }