First steps for gpio and dma

This commit is contained in:
F5OEO
2018-02-26 13:45:28 +00:00
parent 494621e6b2
commit b977a07a34
8 changed files with 266 additions and 2 deletions

View File

@@ -1,4 +1,5 @@
all: ../rpitx ../pissb ../pisstv ../pifsq ../pifm ../piam ../pidcf77 ../piopera
#all: ../rpitx ../pissb ../pisstv ../pifsq ../pifm ../piam ../pidcf77 ../piopera
all: ../rpitx v2rpitx
#CFLAGS = -Wall -g -O2 -D DIGITHIN
CFLAGS = -Wall -g -O2 -Wno-unused-variable
@@ -7,6 +8,19 @@ LDFLAGS = -lm -lrt -lpthread
../rpitx: RpiGpio.c RpiTx.c mailbox.c RpiDma.c raspberry_pi_revision.c calibrationpi2.h calibrationpizero.h calibrationpi3.h
$(CC) $(CFLAGS) -o ../rpitx RpiTx.c RpiGpio.c mailbox.c RpiDma.c raspberry_pi_revision.c $(LDFLAGS)
CFLAGS = -Wall -g -O2 -Wno-unused-variable
LDFLAGS = -lm -lrt -lpthread
CCP = g++
CC = gcc
v2rpitx: gpio.h gpio.cpp dma.h dma.cpp mailbox.c raspberry_pi_revision.c v2rpitx.cpp
$(CC) $(CFLAGS) -c -o mailbox.o mailbox.c
$(CC) $(CFLAGS) -c -o raspberry_pi_revision.o raspberry_pi_revision.c
$(CCP) $(CFLAGS) -o v2rpitx dma.cpp gpio.cpp mailbox.o raspberry_pi_revision.o v2rpitx.cpp $(LDFLAGS)
CFLAGS_Pissb = -Wall -g -O2 -Wno-unused-variable
LDFLAGS_Pissb = -lm -lrt -lpthread -lsndfile

83
src/dma.cpp Normal file
View File

@@ -0,0 +1,83 @@
#include "dma.h"
#include "stdio.h"
extern "C"
{
#include "mailbox.h"
}
#include <unistd.h>
#define BUS_TO_PHYS(x) ((x)&~0xC0000000)
dma::dma(int Channel,int CBSize,int UserMemSize,unsigned int mem_flag)
{
channel=Channel;
mbox.handle = mbox_open();
if (mbox.handle < 0)
{
fprintf(stderr,"Failed to open mailbox\n");
}
unsigned int MemoryRequired=CBSize*sizeof(dma_cb_t)+UserMemSize*sizeof(unsigned int);
int NumPages=(MemoryRequired/PAGE_SIZE)+1;
fprintf(stderr,"%d Size NUM PAGES %d PAGE_SIZE %d\n",MemoryRequired,NumPages,PAGE_SIZE);
mbox.mem_ref = mem_alloc(mbox.handle, NumPages* PAGE_SIZE, PAGE_SIZE, mem_flag);
/* TODO: How do we know that succeeded? */
//printf("mem_ref %x\n", mbox.mem_ref);
mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref);
//printf("bus_addr = %x\n", mbox.bus_addr);
mbox.virt_addr = (uint8_t *)mapmem(BUS_TO_PHYS(mbox.bus_addr), NumPages* PAGE_SIZE);
//printf("virt_addr %p\n", mbox.virt_addr);
virtbase = (uint8_t *)((uint32_t *)mbox.virt_addr);
cbarray = (dma_cb_t *)virtbase; // We place DMA Control Blocks (CB) at beginning of virtual memory
usermem= (unsigned int *)(virtbase+UserMemSize*sizeof(unsigned int)); // user memory is placed after
}
dma::~dma()
{
unmapmem(mbox.virt_addr, NumPages * PAGE_SIZE);
//printf("Unmapmem Done\n");
mem_unlock(mbox.handle, mbox.mem_ref);
//printf("Unmaplock Done\n");
mem_free(mbox.handle, mbox.mem_ref);
}
uint32_t dma::mem_virt_to_phys(volatile void *virt)
{
//MBOX METHOD
uint32_t offset = (uint8_t *)virt - mbox.virt_addr;
return mbox.bus_addr + offset;
}
uint32_t dma::mem_phys_to_virt(volatile uint32_t phys)
{
//MBOX METHOD
uint32_t offset=phys-mbox.bus_addr;
uint32_t result=(uint32_t)((uint8_t *)mbox.virt_addr+offset);
//printf("MemtoVirt:Offset=%lx phys=%lx -> %lx\n",offset,phys,result);
return result;
}
int dma::start()
{
dma_reg.gpioreg[DMA_CONBLK_AD+channel*0x40]=mem_virt_to_phys((void*)cbarray ); // reset to beginning
usleep(100);
dma_reg.gpioreg[DMA_CS+channel*0x40] = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG |DMA_CS_ACTIVE;
return 0;
}
int dma::stop()
{
dma_reg.gpioreg[DMA_CS+channel*0x40] = BCM2708_DMA_RESET;
usleep(1000);
dma_reg.gpioreg[DMA_CS+channel*0x40] = BCM2708_DMA_INT | BCM2708_DMA_END;
usleep(100);
dma_reg.gpioreg[DMA_CONBLK_AD+channel*0x40]=mem_virt_to_phys((void *)cbarray );
usleep(100);
dma_reg.gpioreg[DMA_DEBUG+channel*0x40] = 7; // clear debug error flags
usleep(100);
return 0;
}

47
src/dma.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef DEF_DMA
#define DEF_DMA
#include "stdint.h"
#include "gpio.h"
class dma
{
protected:
struct {
int handle; /* From mbox_open() */
unsigned mem_ref; /* From mem_alloc() */
unsigned bus_addr; /* From mem_lock() */
uint8_t *virt_addr; /* From mapmem() */
} mbox;
typedef struct {
uint32_t info, src, dst, length,
stride, next, pad[2];
} dma_cb_t;
typedef struct {
uint8_t *virtaddr;
uint32_t physaddr;
} page_map_t;
page_map_t *page_map;
uint8_t *virtbase;
int NumPages=0;
int channel; //DMA Channel
dmagpio dma_reg;
public:
dma_cb_t *cbarray;
unsigned int *usermem;
dma(int Channel,int CBSize,int UserMemSize,unsigned int mem_flag);
~dma();
uint32_t mem_virt_to_phys(volatile void *virt);
uint32_t mem_phys_to_virt(volatile uint32_t phys);
int start();
int stop();
};
#endif

51
src/gpio.cpp Normal file
View File

@@ -0,0 +1,51 @@
extern "C"
{
#include "mailbox.h"
}
#include "gpio.h"
#include "raspberry_pi_revision.h"
gpio::gpio(uint32_t base, uint32_t len)
{
gpioreg=( uint32_t *)mapmem(base,len);
}
int gpio::setmode(uint32_t gpio, uint32_t mode)
{
int reg, shift;
reg = gpio/10;
shift = (gpio%10) * 3;
gpioreg[reg] = (gpioreg[reg] & ~(7<<shift)) | (mode<<shift);
return 0;
}
uint32_t gpio::GetPeripheralBase()
{
RASPBERRY_PI_INFO_T info;
uint32_t BCM2708_PERI_BASE=0;
if (getRaspberryPiInformation(&info) > 0)
{
if(info.peripheralBase==RPI_BROADCOM_2835_PERIPHERAL_BASE)
{
BCM2708_PERI_BASE = info.peripheralBase ;
}
if((info.peripheralBase==RPI_BROADCOM_2836_PERIPHERAL_BASE)||(info.peripheralBase==RPI_BROADCOM_2837_PERIPHERAL_BASE))
{
BCM2708_PERI_BASE = info.peripheralBase ;
}
}
return BCM2708_PERI_BASE;
}
//******************** DMA Registers ***************************************
dmagpio::dmagpio():gpio(GetPeripheralBase()+DMA_BASE,DMA_LEN)
{
}

54
src/gpio.h Normal file
View File

@@ -0,0 +1,54 @@
#ifndef DEF_GPIO
#define DEF_GPIO
#include "stdint.h"
class gpio
{
public:
volatile uint32_t *gpioreg;
gpio(uint32_t base, uint32_t len);
int setmode(uint32_t gpio, uint32_t mode);
uint32_t GetPeripheralBase();
};
#define DMA_BASE (0x00007000 )
#define DMA_LEN 0xF00
#define BCM2708_DMA_SRC_IGNOR (1<<11)
#define BCM2708_DMA_SRC_INC (1<<8)
#define BCM2708_DMA_DST_IGNOR (1<<7)
#define BCM2708_DMA_NO_WIDE_BURSTS (1<<26)
#define BCM2708_DMA_WAIT_RESP (1<<3)
#define BCM2708_DMA_D_DREQ (1<<6)
#define BCM2708_DMA_PER_MAP(x) ((x)<<16)
#define BCM2708_DMA_END (1<<1)
#define BCM2708_DMA_RESET (1<<31)
#define BCM2708_DMA_ABORT (1<<30)
#define BCM2708_DMA_INT (1<<2)
#define DMA_CS (0x00/4)
#define DMA_CONBLK_AD (0x04/4)
#define DMA_DEBUG (0x20/4)
#define DMA_CS_RESET (1<<31)
#define DMA_CS_ABORT (1<<30)
#define DMA_CS_DISDEBUG (1<<28)
#define DMA_CS_END (1<<1)
#define DMA_CS_ACTIVE (1<<0)
#define DMA_CS_PRIORITY(x) ((x)&0xf << 16)
#define DMA_CS_PANIC_PRIORITY(x) ((x)&0xf << 20)
class dmagpio:public gpio
{
public:
dmagpio();
};
#endif

View File

@@ -25,6 +25,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -38,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "mailbox.h"
#define PAGE_SIZE (4*1024)
void *mapmem(unsigned base, unsigned size)
{

View File

@@ -25,6 +25,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DEF_MAILBOX
#include <linux/ioctl.h>
// Newer kernels (>= 4.1) use major 249, older ones major 100.
#define MAJOR_NUM_A 249
@@ -34,6 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define LOCAL_DEVICE_FILE_NAME "/dev/rpidatv-mb"
#define VCIO_DEVICE_FILE_NAME "/dev/vcio"
#define PAGE_SIZE (4*1024)
int mbox_open();
void mbox_close(int file_desc);
@@ -48,3 +53,4 @@ void *unmapmem(void *addr, unsigned size);
unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5);
unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout);
unsigned qpu_enable(int file_desc, unsigned enable);
#endif

7
src/v2rpitx.cpp Normal file
View File

@@ -0,0 +1,7 @@
#include "dma.h"
#include "gpio.h"
int main(int argc, char* argv[])
{
}