pi4 detection and CLKOSC according
This commit is contained in:
parent
a3611e265e
commit
2d2d854280
4 changed files with 140 additions and 41 deletions
|
@ -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;
|
clkgpio clk;
|
||||||
clk.print_clock_tree();
|
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);
|
//SimpleTestbpsk(Freq);
|
||||||
|
|
||||||
//SimpleTestAtv(Freq);
|
//SimpleTestAtv(Freq);
|
||||||
info();
|
info(Freq);
|
||||||
}
|
}
|
||||||
|
|
114
src/gpio.cpp
114
src/gpio.cpp
|
@ -31,7 +31,8 @@ extern "C" {
|
||||||
gpio::gpio(uint32_t base, uint32_t len)
|
gpio::gpio(uint32_t base, uint32_t len)
|
||||||
{
|
{
|
||||||
|
|
||||||
gpioreg = (uint32_t *)mapmem(base, len);
|
|
||||||
|
gpioreg = (uint32_t *)mapmem(GetPeripheralBase()+base, len);
|
||||||
gpiolen=len;
|
gpiolen=len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,40 +42,84 @@ gpio::~gpio()
|
||||||
unmapmem((void*)gpioreg,gpiolen);
|
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()
|
uint32_t gpio::GetPeripheralBase()
|
||||||
{
|
{
|
||||||
RASPBERRY_PI_INFO_T info;
|
RASPBERRY_PI_INFO_T info;
|
||||||
uint32_t BCM2708_PERI_BASE =bcm_host_get_peripheral_address();
|
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());
|
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)
|
if(BCM2708_PERI_BASE==0)
|
||||||
{
|
{
|
||||||
dbg_printf(0,"Unknown peripheral base, swith to PI4 \n");
|
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(pi_is_2711)
|
||||||
if (getRaspberryPiInformation(&info) > 0)
|
dbg_printf(1,"Running on Pi4\n");
|
||||||
{
|
|
||||||
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;
|
return BCM2708_PERI_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************** DMA Registers ***************************************
|
//******************** DMA Registers ***************************************
|
||||||
|
|
||||||
dmagpio::dmagpio() : gpio(GetPeripheralBase() + DMA_BASE, DMA_LEN)
|
dmagpio::dmagpio() : gpio( DMA_BASE, DMA_LEN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************** CLK Registers *****************************************
|
// ***************** CLK Registers *****************************************
|
||||||
clkgpio::clkgpio() : gpio(GetPeripheralBase() + CLK_BASE, CLK_LEN)
|
clkgpio::clkgpio() : gpio(CLK_BASE, CLK_LEN)
|
||||||
{
|
{
|
||||||
SetppmFromNTP();
|
SetppmFromNTP();
|
||||||
padgpio level;
|
padgpio level;
|
||||||
|
@ -118,21 +163,21 @@ uint64_t clkgpio::GetPllFrequency(int PllNo)
|
||||||
Freq = XOSC_FREQUENCY;
|
Freq = XOSC_FREQUENCY;
|
||||||
break;
|
break;
|
||||||
case clk_plla:
|
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;
|
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_pllb:Freq=XOSC_FREQUENCY*((uint64_t)gpioreg[PLLB_CTRL]&0x3ff) +XOSC_FREQUENCY*(uint64_t)gpioreg[PLLB_FRAC]/(1<<20);break;
|
||||||
case clk_pllc:
|
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;
|
break;
|
||||||
case clk_plld:
|
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;
|
break;
|
||||||
case clk_hdmi:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
Freq=Freq*(1.0-clk_ppm*1e-6);
|
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;
|
return Freq;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +266,8 @@ int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth)
|
||||||
#define MIN_PLL_RATE 200e6
|
#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 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 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
|
double xtal_freq_recip = 1.0 / XTAL_RATE; // todo PPM correction
|
||||||
int best_divider = 0;
|
int best_divider = 0;
|
||||||
|
|
||||||
|
@ -631,7 +677,7 @@ void clkgpio::SetppmFromNTP()
|
||||||
|
|
||||||
// ************************************** GENERAL GPIO *****************************************************
|
// ************************************** GENERAL GPIO *****************************************************
|
||||||
|
|
||||||
generalgpio::generalgpio() : gpio(GetPeripheralBase() + GENERAL_BASE, GENERAL_LEN)
|
generalgpio::generalgpio() : gpio(/*GetPeripheralBase() + */GENERAL_BASE, GENERAL_LEN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,19 +698,33 @@ int generalgpio::setmode(uint32_t gpio, uint32_t mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
int generalgpio::setpulloff(uint32_t gpio)
|
int generalgpio::setpulloff(uint32_t gpio)
|
||||||
|
{
|
||||||
|
if(!pi_is_2711)
|
||||||
{
|
{
|
||||||
gpioreg[GPPUD]=0;
|
gpioreg[GPPUD]=0;
|
||||||
usleep(150);
|
usleep(150);
|
||||||
gpioreg[GPPUDCLK0]=1<<gpio;
|
gpioreg[GPPUDCLK0]=1<<gpio;
|
||||||
usleep(150);
|
usleep(150);
|
||||||
gpioreg[GPPUDCLK0]=0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ********************************** PWM GPIO **********************************
|
// ********************************** PWM GPIO **********************************
|
||||||
|
|
||||||
pwmgpio::pwmgpio() : gpio(GetPeripheralBase() + PWM_BASE, PWM_LEN)
|
pwmgpio::pwmgpio() : gpio(/*GetPeripheralBase() + */PWM_BASE, PWM_LEN)
|
||||||
{
|
{
|
||||||
|
|
||||||
gpioreg[PWM_CTL] = 0;
|
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) **********************************
|
// ********************************** 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
|
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 (Amplitude) **********************************
|
||||||
|
|
||||||
padgpio::padgpio() : gpio(GetPeripheralBase() + PADS_GPIO, PADS_GPIO_LEN)
|
padgpio::padgpio() : gpio(PADS_GPIO, PADS_GPIO_LEN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/gpio.h
17
src/gpio.h
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
class gpio
|
class gpio
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
bool pi_is_2711=false;
|
||||||
|
uint64_t XOSC_FREQUENCY=19200000;
|
||||||
public:
|
public:
|
||||||
volatile uint32_t *gpioreg = NULL;
|
volatile uint32_t *gpioreg = NULL;
|
||||||
uint32_t gpiolen;
|
uint32_t gpiolen;
|
||||||
|
@ -57,7 +59,7 @@ class dmagpio : public gpio
|
||||||
//************************************ GENERAL GPIO ***************************************
|
//************************************ GENERAL GPIO ***************************************
|
||||||
|
|
||||||
#define GENERAL_BASE (0x00200000)
|
#define GENERAL_BASE (0x00200000)
|
||||||
#define GENERAL_LEN 0xB4
|
#define GENERAL_LEN 0xD0
|
||||||
|
|
||||||
#define GPFSEL0 (0x00 / 4)
|
#define GPFSEL0 (0x00 / 4)
|
||||||
#define GPFSEL1 (0x04 / 4)
|
#define GPFSEL1 (0x04 / 4)
|
||||||
|
@ -66,6 +68,11 @@ class dmagpio : public gpio
|
||||||
#define GPPUDCLK0 (0x98 / 4)
|
#define GPPUDCLK0 (0x98 / 4)
|
||||||
#define GPPUDCLK1 (0x9C / 4)
|
#define GPPUDCLK1 (0x9C / 4)
|
||||||
|
|
||||||
|
#define GPPUPPDN0 (0xBC/4)
|
||||||
|
#define GPPUPPDN1 (0xC0/4)
|
||||||
|
#define GPPUPPDN2 (0xC4/4)
|
||||||
|
#define GPPUPPDN3 (0xC8/4)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
fsel_input,
|
fsel_input,
|
||||||
|
@ -104,6 +111,8 @@ class generalgpio : public gpio
|
||||||
#define GPCLK_DIV_2 (0x84 / 4)
|
#define GPCLK_DIV_2 (0x84 / 4)
|
||||||
#define EMMCCLK_CNTL (0x1C0 / 4)
|
#define EMMCCLK_CNTL (0x1C0 / 4)
|
||||||
#define EMMCCLK_DIV (0x1C4 / 4)
|
#define EMMCCLK_DIV (0x1C4 / 4)
|
||||||
|
#define CM_EMMC2CTL (0x1d0/4)
|
||||||
|
#define CM_EMMC2DIV (0x1d4/4)
|
||||||
|
|
||||||
#define CM_VPUCTL 0x008
|
#define CM_VPUCTL 0x008
|
||||||
#define CM_VPUDIV 0x00c
|
#define CM_VPUDIV 0x00c
|
||||||
|
@ -246,8 +255,8 @@ class generalgpio : public gpio
|
||||||
#define PLLH_STS (0x1660 / 4)
|
#define PLLH_STS (0x1660 / 4)
|
||||||
|
|
||||||
#define XOSC_CTRL (0x1190 / 4)
|
#define XOSC_CTRL (0x1190 / 4)
|
||||||
#define XOSC_FREQUENCY 19200000
|
//#define XOSC_FREQUENCY 19200000
|
||||||
|
//#define XOSC_FREQUENCY 54000000
|
||||||
//Parent PLL
|
//Parent PLL
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,7 @@ phasedmasync::phasedmasync(uint64_t TuneFrequency,uint32_t SampleRateIn,int Numb
|
||||||
clkgpio::SetAdvancedPllMode(true);
|
clkgpio::SetAdvancedPllMode(true);
|
||||||
|
|
||||||
clkgpio::ComputeBestLO(tunefreq,0); // compute PWM divider according to MasterPLL clkgpio::PllFixDivider
|
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)) ;
|
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
|
||||||
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
|
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
|
||||||
freqctl&=0xFFFFF; // Fractionnal is 20bits
|
freqctl&=0xFFFFF; // Fractionnal is 20bits
|
||||||
|
|
Loading…
Reference in a new issue