From 517ae1811ed0b1a97a386b197f758a0adf62dc26 Mon Sep 17 00:00:00 2001 From: pa3gsb Date: Thu, 18 Apr 2024 11:11:40 +0200 Subject: [PATCH] fpga loader utility for pi5 --- SBC/README.md | 2 - SBC/rpi-5/utility/gatewareloader/Makefile | 44 ++++ SBC/rpi-5/utility/gatewareloader/README | 8 + SBC/rpi-5/utility/gatewareloader/loadFPGA.c | 247 ++++++++++++++++++++ SBC/rpi-5/utility/gatewareloader/loadFPGA.h | 3 + 5 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 SBC/rpi-5/utility/gatewareloader/Makefile create mode 100644 SBC/rpi-5/utility/gatewareloader/README create mode 100644 SBC/rpi-5/utility/gatewareloader/loadFPGA.c create mode 100644 SBC/rpi-5/utility/gatewareloader/loadFPGA.h diff --git a/SBC/README.md b/SBC/README.md index 014ccb6..a951a71 100644 --- a/SBC/README.md +++ b/SBC/README.md @@ -3,5 +3,3 @@ RadioBerry V2.0 - Ham radio cape for Raspberry PI RadioBerry is working together with different Single Board Computers (SBC). - -New development is foccusing on the rpi-4. diff --git a/SBC/rpi-5/utility/gatewareloader/Makefile b/SBC/rpi-5/utility/gatewareloader/Makefile new file mode 100644 index 0000000..0eab32d --- /dev/null +++ b/SBC/rpi-5/utility/gatewareloader/Makefile @@ -0,0 +1,44 @@ +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O3 +CC = gcc +INCLUDE = -I/usr/local/include +CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe + +LDFLAGS = -L/usr/local/lib +LDLIBS = -lpthread -lm + +SRC = loadFPGA.c + +OBJ = $(SRC:.c=.o) + +BINS = $(SRC:.c=) + +all: + $Q cat README.TXT + $Q echo " $(BINS)" | fmt + $Q echo "" + +really-all: $(BINS) + +loadFPGA: loadFPGA.o + $Q echo [link] + $Q $(CC) -o $@ loadFPGA.o $(LDFLAGS) $(LDLIBS) + +.c.o: + $Q echo [CC] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +clean: + $Q echo "[Clean]" + $Q rm -f $(OBJ) *~ core tags $(BINS) + +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +depend: + makedepend -Y $(SRC) \ No newline at end of file diff --git a/SBC/rpi-5/utility/gatewareloader/README b/SBC/rpi-5/utility/gatewareloader/README new file mode 100644 index 0000000..85c0141 --- /dev/null +++ b/SBC/rpi-5/utility/gatewareloader/README @@ -0,0 +1,8 @@ + +Gatewareloader. + +- make loadFPGA + +- copy your radioberry.rbf into the folder + +- sudo ./loadFPGA \ No newline at end of file diff --git a/SBC/rpi-5/utility/gatewareloader/loadFPGA.c b/SBC/rpi-5/utility/gatewareloader/loadFPGA.c new file mode 100644 index 0000000..17f8e90 --- /dev/null +++ b/SBC/rpi-5/utility/gatewareloader/loadFPGA.c @@ -0,0 +1,247 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "loadFPGA.h" + + +#define iPinCONF_DONE 22 +#define iPinNSTATUS 26 + +#define oPinNCONFIG 27 +#define oPinDATA 13 +#define oPinDCLK 24 + + +volatile uint32_t *GPIOBase = NULL ; +volatile uint32_t *RIOBase = NULL ; +volatile uint32_t *PADBase = NULL ; +volatile uint32_t *Pad = NULL ; + + +#define GPIO_FUNC_RIO 5 +#define PAD_FUNC_IN 0xc8 +#define PAD_FUNC_OUT 0x10 + +typedef struct{ + uint32_t status; + uint32_t ctrl; +}GPIOregs; + +#define GPIO ((GPIOregs*)GPIOBase) +typedef struct +{ + uint32_t out; + uint32_t oe; + uint32_t in; + uint32_t InSync; +} rioregs; + +#define rio ((rioregs *)RIOBase) +#define rioXOR ((rioregs *)(RIOBase + 0x1000 / 4)) +#define rioSET ((rioregs *)(RIOBase + 0x2000 / 4)) +#define rioCLR ((rioregs *)(RIOBase + 0x3000 / 4)) + + +static void initialize_gpio_for_output(uint32_t pin) { + GPIO[pin].ctrl=GPIO_FUNC_RIO; + Pad[pin] = PAD_FUNC_OUT; + rioSET->oe = 0x01<in = 0x01<oe = 0x01<oe = 0x01<out = 0x01<oe = 0x01<out = 0x01<in>>pin & 0x01); +} + +static uint32_t get_pinhigh(uint32_t pin) { + return (GPIO[pin].status & 0x80000); +} + +static uint32_t get_pinlow(uint32_t pin) { + return (GPIO[pin].status & 0x40000); +} + + +int main (int argc, char **argv) +{ + printf ("\n\n"); + printf ("=======================================================\n") ; + printf ("=== Raspberry Pi 5 - RadioBerry Gateware Loader ===\n") ; + printf ("=======================================================\n") ; + printf ("\n\n"); + + int memfd = open("/dev/mem", O_RDWR | O_SYNC); + uint32_t *map = (uint32_t *)mmap( + NULL, + 64 * 1024 * 1024, + (PROT_READ | PROT_WRITE), + MAP_SHARED, + memfd, + 0x1f00000000 + ); + if (map == MAP_FAILED) + { + printf("mmap failed: %s\n", strerror(errno)); + return (-1); + }; + close(memfd); + uint32_t *PERIBase = map; + GPIOBase = PERIBase + 0xD0000 / 4; + RIOBase = PERIBase + 0xe0000 / 4; + PADBase = PERIBase + 0xf0000 / 4; + Pad = PADBase + 1; + + initialize_gpio_for_input(iPinCONF_DONE); + initialize_gpio_for_input(iPinNSTATUS); + + initialize_gpio_for_output(oPinNCONFIG); + initialize_gpio_for_output(oPinDATA); + initialize_gpio_for_output(oPinDCLK); + + fprintf(stderr, "Init done.\n"); + + /* Processing and Programming */ + processFileInput( ); + + return 0; +} + +void processFileInput( ) +{ + int seek_position = 0; /* file pointer position */ + long int file_size = 0; /* programming file size */ + int one_byte = 0; /* the byte to program */ + long int i = 0; /* standard counter variable */ + + char filename[30]; + strcpy(filename, "radioberry.rbf"); + printf("%s will be loaded.\n", filename); + + FILE *finputid; + + /* Open programming file as READ and in BINARY */ + finputid = fopen( "radioberry.rbf", "rb" ); + if (finputid == NULL) { + perror("Error opening file"); + return 1; + } + + /* Start configuration */ + if (prepareLoading() == -1) return; + + fprintf(stderr, "now gateware loading....\n"); + + sleep(1); + + char byte; + while (fread(&byte, sizeof(char), 1, finputid) == 1) { + programByte( byte ); + } + + //fprintf(stderr, "nstatus level = %d \n", read_pin(iPinNSTATUS)); + //fprintf(stderr, "conf level = %d \n", read_pin(iPinCONF_DONE)); + + sleep(1); + + /* Check if loading succeeded*/ + if (read_pin(iPinNSTATUS) == 0) { + fprintf( stderr, "Error: programming failed; nstatus is low\n" ); + return; + } else if (read_pin(iPinCONF_DONE) == 0) { + fprintf( stderr, "Error: programming failed; conf done is low\n" ); + return; + } + + set_pin(oPinDCLK); + usleep(1); + clr_pin(oPinDCLK); + usleep(1); + set_pin(oPinDCLK); + usleep(1); + clr_pin(oPinDCLK); + usleep(1); + set_pin(oPinDCLK); + usleep(1); + clr_pin(oPinDCLK); + + fprintf( stdout, "gateware loaded succeeded\n" ); + + if ( finputid ) fclose(finputid); +} + + +void programByte( char one_byte ) +{ + char bit = 0; + int i = 0; + + /* write from LSb to MSb */ + for ( i = 0; i < 8; i++ ) + { + bit = one_byte >> i; + bit = bit & 0x1; + + if (bit) set_pin(oPinDATA); else clr_pin(oPinDATA); + fprintf(stderr, ""); + set_pin(oPinDCLK); + clr_pin(oPinDCLK); + } +} + + +int prepareLoading() +{ + fprintf( stdout, "Info: prepareLoading\n" ); + + //fprintf(stderr, "nstatus level = %d \n", read_pin(iPinNSTATUS)); + //fprintf(stderr, "conf level = %d \n", read_pin(iPinCONF_DONE)); + + clr_pin(oPinNCONFIG); + clr_pin(oPinDATA); + clr_pin(oPinDCLK); + sleep(1); + set_pin(oPinNCONFIG); + + int count = 0; + while (read_pin(iPinNSTATUS) == 0) { + count++; + sleep(10); + if (count >= 255) { + fprintf( stderr, "Error: prepareLoading failed\n" ); + return -1; + } + } + + //fprintf(stderr, "nstatus level = %d \n", read_pin(iPinNSTATUS)); + //fprintf(stderr, "conf level = %d \n", read_pin(iPinCONF_DONE)); + fprintf( stdout, "Info: prepareLoading done.\n" ); + + return 0; +} diff --git a/SBC/rpi-5/utility/gatewareloader/loadFPGA.h b/SBC/rpi-5/utility/gatewareloader/loadFPGA.h new file mode 100644 index 0000000..fc18fae --- /dev/null +++ b/SBC/rpi-5/utility/gatewareloader/loadFPGA.h @@ -0,0 +1,3 @@ +void processFileInput ( ); +int prepareLoading (); +void programByte ( char one_byte ); \ No newline at end of file