Fix DMA memory bug

v2beta
F5OEO 2018-02-27 16:36:04 +00:00
rodzic 61afc7962e
commit 0841c37522
5 zmienionych plików z 65 dodań i 25 usunięć

Wyświetl plik

@ -24,19 +24,26 @@ dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize)
usermemsize=UserMemSize;
GetRpiInfo(); // Fill mem_flag and dram_phys_base
unsigned int MemoryRequired=CBSize*sizeof(dma_cb_t)+UserMemSize*sizeof(unsigned int);
uint32_t MemoryRequired=CBSize*sizeof(dma_cb_t)+UserMemSize*sizeof(uint32_t);
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);
fprintf(stderr,"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);
fprintf(stderr,"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);
fprintf(stderr,"virt_addr %p\n", mbox.virt_addr);
virtbase = (uint8_t *)((uint32_t *)mbox.virt_addr);
fprintf(stderr,"virtbase %p\n", virtbase);
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
fprintf(stderr,"cbarray %p\n", cbarray);
usermem= (unsigned int *)(virtbase+CBSize*sizeof(dma_cb_t)); // user memory is placed after
fprintf(stderr,"usermem %p\n", usermem);
dma_reg.gpioreg[DMA_CS+channel*0x40] = BCM2708_DMA_RESET;
usleep(100);
dma_reg.gpioreg[DMA_CONBLK_AD+channel*0x40]=mem_virt_to_phys((void*)cbarray ); // reset to beginning
}
void dma::GetRpiInfo()
@ -66,10 +73,11 @@ void dma::GetRpiInfo()
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);
}
@ -91,6 +99,8 @@ uint32_t dma::mem_phys_to_virt(volatile uint32_t phys)
int dma::start()
{
dma_reg.gpioreg[DMA_CS+channel*0x40] = BCM2708_DMA_RESET;
usleep(100);
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;
@ -110,3 +120,10 @@ int dma::stop()
return 0;
}
uint32_t dma::getcbposition()
{
return mem_phys_to_virt((uint32_t)(dma_reg.gpioreg[DMA_CONBLK_AD+channel*0x40]))-(uint32_t)virtbase;
// dma_reg.gpioreg[DMA_CONBLK_AD+channel*0x40]-mem_virt_to_phys((void *)cbarray );
}

Wyświetl plik

@ -31,6 +31,17 @@
#define DMA_CONBLK_AD (0x04/4)
#define DMA_DEBUG (0x20/4)
//Page 61
#define DREQ_PCM_TX 2
#define DREQ_PCM_RX 3
#define DREQ_SMI 4
#define DREQ_PWM 5
#define DREQ_SPI_TX 6
#define DREQ_SPI_RX 7
#define DREQ_SPI_SLAVE_TX 8
#define DREQ_SPI_SLAVE_RX 9
class dma
{
protected:
@ -44,7 +55,7 @@ class dma
typedef struct {
uint32_t info, src, dst, length,
stride, next, pad[2];
} dma_cb_t;
} dma_cb_t; //8*4=32 bytes
typedef struct {
uint8_t *virtaddr;
@ -63,7 +74,7 @@ class dma
public:
dma_cb_t *cbarray;
uint32_t cbsize;
unsigned int *usermem;
uint32_t *usermem;
uint32_t usermemsize;
@ -74,6 +85,7 @@ class dma
void GetRpiInfo();
int start();
int stop();
uint32_t getcbposition();
};
#endif

Wyświetl plik

@ -20,29 +20,31 @@ void fmdmasync::SetDmaAlgo()
// Write a frequency sample
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS /* BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5)*/;
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt]);
cbp->dst = 0x7E000000 | GPCLK_DIV | CLK_BASE ;
cbp->dst = 0x7E000000 | (GPCLK_DIV<<2) | CLK_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp : sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
cbp++;
// Delay
cbp->info = BCM2708_DMA_SRC_IGNOR |/* BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |*/ BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(2);
cbp->src = mem_virt_to_phys(usermem); // Data is not important as we use it only to feed the PWM
cbp->dst = 0x7E000000 | PWM_FIFO | PWM_BASE ;
cbp->info = /*BCM2708_DMA_SRC_IGNOR | */BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
cbp->dst = 0x7E000000 | (PWM_FIFO<<2) | PWM_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
cbp++;
}
cbp--;
cbp->next = mem_virt_to_phys(cbarray); // We loop to the first CB
//fprintf(stderr,"Last cbp : src %x dest %x next %x\n",cbp->src,cbp->dst,cbp->next);
}
void fmdmasync::FillMemory(uint32_t FreqDivider,uint32_t FreqFractionnal)

Wyświetl plik

@ -67,7 +67,8 @@ int clkgpio::SetPllNumber(int PllNo,int MashType)
if(PllNo<8)
pllnumber=PllNo;
else
pllnumber=clk_pllc;
pllnumber=clk_pllc;
if(MashType<4)
Mash=MashType;
else
@ -82,6 +83,7 @@ uint64_t clkgpio::GetPllFrequency(int PllNo)
uint64_t Freq=0;
switch(PllNo)
{
case clk_osc:Freq=XOSC_FREQUENCY;break;
case clk_plla:Freq=XOSC_FREQUENCY*((uint64_t)gpioreg[PLLA_CTRL]&0x3ff) +XOSC_FREQUENCY*(uint64_t)gpioreg[PLLA_FRAC]/(1<<20);break;
//case clk_pllb:Freq=XOSC_FREQUENCY*((uint64_t)gpioreg[PLLB_CTRL]&0x3ff) +XOSC_FREQUENCY*(uint64_t)gpioreg[PLLB_FRAC]/(1<<20);break;
case clk_pllc:Freq=XOSC_FREQUENCY*((uint64_t)gpioreg[PLLC_CTRL]&0x3ff) +XOSC_FREQUENCY*(uint64_t)gpioreg[PLLC_FRAC]/(1<<20);break;
@ -244,7 +246,7 @@ int pwmgpio::SetPllNumber(int PllNo,int MashType)
Mash=MashType;
else
Mash=0;
clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is START CLK
clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(0 << 4) ; //4 is STOP CLK
Pllfrequency=GetPllFrequency(pllnumber);
return 0;
}
@ -263,7 +265,7 @@ int pwmgpio::SetFrequency(uint64_t Frequency)
uint32_t FreqFractionnal=(uint32_t) (4096*(Freqresult-(double)FreqDivider));
if((FreqDivider>4096)||(FreqDivider<2)) fprintf(stderr,"Frequency out of range\n");
clk.gpioreg[PWMCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal;
clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is STAR CLK
return 0;
}
@ -277,9 +279,9 @@ int pwmgpio::SetMode(int Mode) //Mode should be only for SYNC or a Data serializ
gpioreg[PWM_FIFO]=0xAAAAAAAA;
gpioreg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD;
usleep(100);
gpioreg[PWM_CTL] = PWMCTL_CLRF;
//gpioreg[PWM_CTL] = PWMCTL_CLRF;
//pwm_reg[PWM_CTL] = PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1|PWMCTL_RPTL1; //PWM0 in Repeat mode
gpioreg[PWM_CTL] = PWMCTL_USEF1 | PWMCTL_PWEN1; //PWM0 in Repeat mode
return 0;

Wyświetl plik

@ -2,6 +2,7 @@
#include "dma.h"
#include "gpio.h"
#include "fmdmasync.h"
#include "stdio.h"
int main(int argc, char* argv[])
{
@ -14,14 +15,20 @@ int main(int argc, char* argv[])
pwmgpio pwm;
pwm.SetPllNumber(clk_plld,1);
pwm.SetFrequency(1000000);
pwm.SetFrequency(300000);
pwm.SetMode(0);
clk.SetFrequency(89000000);
fmdmasync fmtest(14,4000);
//clk.SetFrequency(89100000);
fmdmasync fmtest(14,16);
fmtest.start();
sleep(20);
for(int i=0;i<10000;i++)
{
usleep(100);
printf("cb -> %x\n",fmtest.getcbposition());
}
sleep(5);
fmtest.stop();
/*
{
for(int i=0;i<10000;i++)