From 0841c375220b97c7bb7c8b85af073743f453a1ad Mon Sep 17 00:00:00 2001 From: F5OEO Date: Tue, 27 Feb 2018 16:36:04 +0000 Subject: [PATCH] Fix DMA memory bug --- src/dma.cpp | 31 ++++++++++++++++++++++++------- src/dma.h | 16 ++++++++++++++-- src/fmdmasync.cpp | 14 ++++++++------ src/gpio.cpp | 12 +++++++----- src/v2rpitx.cpp | 17 ++++++++++++----- 5 files changed, 65 insertions(+), 25 deletions(-) diff --git a/src/dma.cpp b/src/dma.cpp index 5195ab2..b63e827 100644 --- a/src/dma.cpp +++ b/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 ); +} + diff --git a/src/dma.h b/src/dma.h index 0ed24c2..b9f57ca 100644 --- a/src/dma.h +++ b/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 diff --git a/src/fmdmasync.cpp b/src/fmdmasync.cpp index 921194f..630fc9e 100644 --- a/src/fmdmasync.cpp +++ b/src/fmdmasync.cpp @@ -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) diff --git a/src/gpio.cpp b/src/gpio.cpp index 47eba0d..f447093 100644 --- a/src/gpio.cpp +++ b/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; diff --git a/src/v2rpitx.cpp b/src/v2rpitx.cpp index 7b9034b..97e0cd8 100644 --- a/src/v2rpitx.cpp +++ b/src/v2rpitx.cpp @@ -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++)