pi4 detection and CLKOSC according

pi4
F5OEO 2019-08-18 13:32:09 +01:00 zatwierdzone przez f5oeo
rodzic a3611e265e
commit 2d2d854280
4 zmienionych plików z 140 dodań i 41 usunięć

Wyświetl plik

@ -701,10 +701,40 @@ void SimpleTestAtv(uint64_t Freq)
}
}
void info(void)
void info(uint64_t Freq)
{
generalgpio genpio;
fprintf(stderr, "GPIOPULL =%x\n", genpio.gpioreg[GPPUDCLK0]);
#define PULL_OFF 0
#define PULL_DOWN 1
#define PULL_UP 2
/*genpio.gpioreg[GPPUD] = 0; //PULL_DOWN;
usleep(150);
genpio.gpioreg[GPPUDCLK0] = (1 << 4); //GPIO CLK is GPIO 4
usleep(150);
genpio.gpioreg[GPPUDCLK0] = (0); //GPIO CLK is GPIO 4
*/
//genpio.setpulloff(4);
padgpio pad;
pad.setlevel(7);
clkgpio clk;
clk.print_clock_tree();
clk.SetPllNumber(clk_plld, 2);
clk.enableclk(4);
//clk.SetAdvancedPllMode(true);
//clk.SetPLLMasterLoop(0,4,0);
//clk.Setppm(+7.7);
clk.SetCenterFrequency(Freq, 1000);
double freqresolution = clk.GetFrequencyResolution();
double RealFreq = clk.GetRealFrequency(0);
fprintf(stderr, "Frequency resolution=%f Error freq=%f\n", freqresolution, RealFreq);
int Deviation = 0;
clk.SetFrequency(000);
sleep(10);
clk.disableclk(4);
}
@ -744,5 +774,5 @@ int main(int argc, char *argv[])
//SimpleTestbpsk(Freq);
//SimpleTestAtv(Freq);
info();
info(Freq);
}

Wyświetl plik

@ -31,7 +31,8 @@ extern "C" {
gpio::gpio(uint32_t base, uint32_t len)
{
gpioreg = (uint32_t *)mapmem(base, len);
gpioreg = (uint32_t *)mapmem(GetPeripheralBase()+base, len);
gpiolen=len;
}
@ -41,40 +42,84 @@ gpio::~gpio()
unmapmem((void*)gpioreg,gpiolen);
}
uint32_t get_hwbase(void)
{
const char *ranges_file = "/proc/device-tree/soc/ranges";
uint8_t ranges[12];
FILE *fd;
uint32_t ret = 0;
memset(ranges, 0, sizeof(ranges));
if ((fd = fopen(ranges_file, "rb")) == NULL)
{
printf("Can't open '%s'\n", ranges_file);
}
else if (fread(ranges, 1, sizeof(ranges), fd) >= 8)
{
ret = (ranges[4] << 24) |
(ranges[5] << 16) |
(ranges[6] << 8) |
(ranges[7] << 0);
if (!ret)
ret = (ranges[8] << 24) |
(ranges[9] << 16) |
(ranges[10] << 8) |
(ranges[11] << 0);
if ((ranges[0] != 0x7e) ||
(ranges[1] != 0x00) ||
(ranges[2] != 0x00) ||
(ranges[3] != 0x00) ||
((ret != 0x20000000) && (ret != 0x3f000000) && (ret != 0xfe000000)))
{
printf("Unexpected ranges data (%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x)\n",
ranges[0], ranges[1], ranges[2], ranges[3],
ranges[4], ranges[5], ranges[6], ranges[7],
ranges[8], ranges[9], ranges[10], ranges[11]);
ret = 0;
}
}
else
{
printf("Ranges data too short\n");
}
fclose(fd);
return ret;
}
uint32_t gpio::GetPeripheralBase()
{
RASPBERRY_PI_INFO_T info;
uint32_t BCM2708_PERI_BASE = bcm_host_get_peripheral_address();
dbg_printf(1,"Peri Base = %x SDRAM %x\n",bcm_host_get_peripheral_address(),bcm_host_get_sdram_address());
uint32_t BCM2708_PERI_BASE =bcm_host_get_peripheral_address();
dbg_printf(1,"Peri Base = %x SDRAM %x\n",/*get_hwbase()*/bcm_host_get_peripheral_address(),bcm_host_get_sdram_address());
if(BCM2708_PERI_BASE==0xFE000000) // Fixme , could be inspect without this hardcoded value
{
pi_is_2711=true; //Rpi4
XOSC_FREQUENCY=54000000;
}
if(BCM2708_PERI_BASE==0)
{
dbg_printf(0,"Unknown peripheral base, swith to PI4 \n");
BCM2708_PERI_BASE=0xfe000000;
BCM2708_PERI_BASE=0xfe000000;
XOSC_FREQUENCY=54000000;
pi_is_2711=true;
}
/*
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;
}
}*/
if(pi_is_2711)
dbg_printf(1,"Running on Pi4\n");
return BCM2708_PERI_BASE;
}
//******************** DMA Registers ***************************************
dmagpio::dmagpio() : gpio(GetPeripheralBase() + DMA_BASE, DMA_LEN)
dmagpio::dmagpio() : gpio( DMA_BASE, DMA_LEN)
{
}
// ***************** CLK Registers *****************************************
clkgpio::clkgpio() : gpio(GetPeripheralBase() + CLK_BASE, CLK_LEN)
clkgpio::clkgpio() : gpio(CLK_BASE, CLK_LEN)
{
SetppmFromNTP();
padgpio level;
@ -118,21 +163,21 @@ uint64_t clkgpio::GetPllFrequency(int PllNo)
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);
Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLA_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLA_FRAC] / (1 << 20))/(2*(gpioreg[PLLA_CTRL] >> 12)&0x7);
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);
Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLC_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLC_FRAC] / (1 << 20))/(2*(gpioreg[PLLC_CTRL] >> 12)&0x7) ;
break;
case clk_plld:
Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLD_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLD_FRAC]) / (1 << 20)) / (gpioreg[PLLD_PER] >> 1);
Freq =( (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLD_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLD_FRAC]) / (1 << 20)) / (2*gpioreg[PLLD_PER] >> 1))/((gpioreg[PLLD_CTRL] >> 12)&0x7) ;
break;
case clk_hdmi:
Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLH_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLH_FRAC] / (1 << 20);
Freq =( XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLH_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLH_FRAC] / (1 << 20))/(2*(gpioreg[PLLH_CTRL] >> 12)&0x7) ;
break;
}
Freq=Freq*(1.0-clk_ppm*1e-6);
dbg_printf(1, "Freq PLL no %d= %llu\n",PllNo, Freq);
dbg_printf(1, "Pi4=%d Xosc = %llu Freq PLL no %d= %llu\n",pi_is_2711,XOSC_FREQUENCY,PllNo, Freq);
return Freq;
}
@ -221,7 +266,8 @@ int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth)
#define MIN_PLL_RATE 200e6
#define MIN_PLL_RATE_USE_PDIV 1500e6 //1700 works but some ticky breaks in clock..PLL should be at limit
#define MAX_PLL_RATE 4e9
#define XTAL_RATE 19.2e6
#define XTAL_RATE XOSC_FREQUENCY
//Pi4 seems 54Mhz
double xtal_freq_recip = 1.0 / XTAL_RATE; // todo PPM correction
int best_divider = 0;
@ -631,7 +677,7 @@ void clkgpio::SetppmFromNTP()
// ************************************** GENERAL GPIO *****************************************************
generalgpio::generalgpio() : gpio(GetPeripheralBase() + GENERAL_BASE, GENERAL_LEN)
generalgpio::generalgpio() : gpio(/*GetPeripheralBase() + */GENERAL_BASE, GENERAL_LEN)
{
}
@ -653,18 +699,32 @@ int generalgpio::setmode(uint32_t gpio, uint32_t mode)
int generalgpio::setpulloff(uint32_t gpio)
{
gpioreg[GPPUD]=0;
usleep(150);
gpioreg[GPPUDCLK0]=1<<gpio;
usleep(150);
gpioreg[GPPUDCLK0]=0;
if(!pi_is_2711)
{
gpioreg[GPPUD]=0;
usleep(150);
gpioreg[GPPUDCLK0]=1<<gpio;
usleep(150);
gpioreg[GPPUDCLK0]=0;
}
else
{
uint32_t bits;
uint32_t pull=0; // 0 OFF, 1 = UP, 2= DOWN
int shift = (gpio & 0xf) << 1;
bits = gpioreg[GPPUPPDN0 + (gpio>>4)];
bits &= ~(3 << shift);
bits |= (pull << shift);
gpioreg[GPPUPPDN0 + (gpio>>4)] = bits;
}
return 0;
}
// ********************************** PWM GPIO **********************************
pwmgpio::pwmgpio() : gpio(GetPeripheralBase() + PWM_BASE, PWM_LEN)
pwmgpio::pwmgpio() : gpio(/*GetPeripheralBase() + */PWM_BASE, PWM_LEN)
{
gpioreg[PWM_CTL] = 0;
@ -814,7 +874,7 @@ int pwmgpio::SetPrediv(int predivisor) //Mode should be only for SYNC or a Data
// ********************************** PCM GPIO (I2S) **********************************
pcmgpio::pcmgpio() : gpio(GetPeripheralBase() + PCM_BASE, PCM_LEN)
pcmgpio::pcmgpio() : gpio(PCM_BASE, PCM_LEN)
{
gpioreg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block
}
@ -899,7 +959,7 @@ int pcmgpio::SetPrediv(int predivisor) //Carefull we use a 10 fixe divisor for n
// ********************************** PADGPIO (Amplitude) **********************************
padgpio::padgpio() : gpio(GetPeripheralBase() + PADS_GPIO, PADS_GPIO_LEN)
padgpio::padgpio() : gpio(PADS_GPIO, PADS_GPIO_LEN)
{
}

Wyświetl plik

@ -7,7 +7,9 @@
class gpio
{
public:
bool pi_is_2711=false;
uint64_t XOSC_FREQUENCY=19200000;
public:
volatile uint32_t *gpioreg = NULL;
uint32_t gpiolen;
@ -57,7 +59,7 @@ class dmagpio : public gpio
//************************************ GENERAL GPIO ***************************************
#define GENERAL_BASE (0x00200000)
#define GENERAL_LEN 0xB4
#define GENERAL_LEN 0xD0
#define GPFSEL0 (0x00 / 4)
#define GPFSEL1 (0x04 / 4)
@ -66,6 +68,11 @@ class dmagpio : public gpio
#define GPPUDCLK0 (0x98 / 4)
#define GPPUDCLK1 (0x9C / 4)
#define GPPUPPDN0 (0xBC/4)
#define GPPUPPDN1 (0xC0/4)
#define GPPUPPDN2 (0xC4/4)
#define GPPUPPDN3 (0xC8/4)
enum
{
fsel_input,
@ -104,6 +111,8 @@ class generalgpio : public gpio
#define GPCLK_DIV_2 (0x84 / 4)
#define EMMCCLK_CNTL (0x1C0 / 4)
#define EMMCCLK_DIV (0x1C4 / 4)
#define CM_EMMC2CTL (0x1d0/4)
#define CM_EMMC2DIV (0x1d4/4)
#define CM_VPUCTL 0x008
#define CM_VPUDIV 0x00c
@ -246,8 +255,8 @@ class generalgpio : public gpio
#define PLLH_STS (0x1660 / 4)
#define XOSC_CTRL (0x1190 / 4)
#define XOSC_FREQUENCY 19200000
//#define XOSC_FREQUENCY 19200000
//#define XOSC_FREQUENCY 54000000
//Parent PLL
enum
{

Wyświetl plik

@ -41,7 +41,7 @@ phasedmasync::phasedmasync(uint64_t TuneFrequency,uint32_t SampleRateIn,int Numb
clkgpio::SetAdvancedPllMode(true);
clkgpio::ComputeBestLO(tunefreq,0); // compute PWM divider according to MasterPLL clkgpio::PllFixDivider
double FloatMult=((double)(tunefreq)*clkgpio::PllFixDivider)/(double)(XOSC_FREQUENCY);
double FloatMult=((double)(tunefreq)*clkgpio::PllFixDivider)/(double)(pwmgpio::XOSC_FREQUENCY);
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
freqctl&=0xFFFFF; // Fractionnal is 20bits