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; 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);
} }

Wyświetl plik

@ -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)
{ {
} }
@ -653,18 +699,32 @@ int generalgpio::setmode(uint32_t gpio, uint32_t mode)
int generalgpio::setpulloff(uint32_t gpio) int generalgpio::setpulloff(uint32_t gpio)
{ {
gpioreg[GPPUD]=0; if(!pi_is_2711)
usleep(150); {
gpioreg[GPPUDCLK0]=1<<gpio; gpioreg[GPPUD]=0;
usleep(150); usleep(150);
gpioreg[GPPUDCLK0]=0; 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; 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)
{ {
} }

Wyświetl plik

@ -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
{ {

Wyświetl plik

@ -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