kopia lustrzana https://github.com/F5OEO/rpitx
Fix DMA memory bug
rodzic
61afc7962e
commit
0841c37522
31
src/dma.cpp
31
src/dma.cpp
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
16
src/dma.h
16
src/dma.h
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
12
src/gpio.cpp
12
src/gpio.cpp
|
@ -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;
|
||||
|
|
|
@ -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++)
|
||||
|
|
Ładowanie…
Reference in New Issue