Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
```
Expand Down
10 changes: 10 additions & 0 deletions include/bcm283x/bcm283x.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
#include <stdbool.h>
#include <stdint.h>

#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

Expand All @@ -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"
Expand Down
157 changes: 152 additions & 5 deletions source/bcm283x/bcm283x.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <assert.h>
#include <stddef.h>

#include <bcm_host.h>
#include <stdint.h>
#include <stdio.h>

#include "bcm283x.h"
#include "log.h"
Expand All @@ -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);
Expand Down Expand Up @@ -57,4 +57,151 @@ void bcm283x_init()
void bcm283x_delay_microseconds(uint32_t microseconds)
{
microsleep(microseconds);
}
}

/**
@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;
}
7 changes: 3 additions & 4 deletions source/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <argp.h>
#include <bcm_host.h>
#include <fcntl.h>
#include <math.h>
#include <poll.h>
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions source/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ 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;
}

int32_t result = close(file);
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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down