#258 Pi5 full PWM support
This commit is contained in:
@@ -118,14 +118,20 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ;
|
|||||||
|
|
||||||
// Port function select bits
|
// Port function select bits
|
||||||
|
|
||||||
#define FSEL_INPT 0b000
|
#define FSEL_INPT 0b000 //0
|
||||||
#define FSEL_OUTP 0b001
|
#define FSEL_OUTP 0b001 //1
|
||||||
#define FSEL_ALT0 0b100
|
#define FSEL_ALT0 0b100 //4
|
||||||
#define FSEL_ALT1 0b101
|
#define FSEL_ALT1 0b101 //5
|
||||||
#define FSEL_ALT2 0b110
|
#define FSEL_ALT2 0b110 //6
|
||||||
#define FSEL_ALT3 0b111
|
#define FSEL_ALT3 0b111 //7
|
||||||
#define FSEL_ALT4 0b011
|
#define FSEL_ALT4 0b011 //3
|
||||||
#define FSEL_ALT5 0b010
|
#define FSEL_ALT5 0b010 //2
|
||||||
|
//RP1 defines
|
||||||
|
#define FSEL_ALT6 8
|
||||||
|
#define FSEL_ALT7 9
|
||||||
|
#define FSEL_ALT8 10
|
||||||
|
#define FSEL_ALT9 11
|
||||||
|
|
||||||
|
|
||||||
//RP1 chip (@Pi5) - 3.1.1. Function select
|
//RP1 chip (@Pi5) - 3.1.1. Function select
|
||||||
#define RP1_FSEL_ALT0 0x00
|
#define RP1_FSEL_ALT0 0x00
|
||||||
@@ -166,10 +172,40 @@ const unsigned int RP1_PAD_IC_DEFAULT_FROM9 = 0x96; //pull-down, Schmitt
|
|||||||
const unsigned int RP1_PAD_DRIVE_MASK = 0x00000030;
|
const unsigned int RP1_PAD_DRIVE_MASK = 0x00000030;
|
||||||
const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK);
|
const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK);
|
||||||
|
|
||||||
|
const unsigned int RP1_PWM0_GLOBAL_CTRL = 0;
|
||||||
|
const unsigned int RP1_PWM0_FIFO_CTRL = 1;
|
||||||
|
const unsigned int RP1_PWM0_COMMON_RANGE= 2;
|
||||||
|
const unsigned int RP1_PWM0_COMMON_DUTY = 3;
|
||||||
|
const unsigned int RP1_PWM0_DUTY_FIFO = 4;
|
||||||
|
const unsigned int RP1_PWM0_CHAN_START = 5;
|
||||||
|
//offset channel
|
||||||
|
const unsigned int RP1_PWM0_CHAN_CTRL = 0;
|
||||||
|
const unsigned int RP1_PWM0_CHAN_RANGE = 1;
|
||||||
|
const unsigned int RP1_PWM0_CHAN_PHASE = 2;
|
||||||
|
const unsigned int RP1_PWM0_CHAN_DUTY = 3;
|
||||||
|
const unsigned int RP1_PWM0_CHAN_OFFSET= 4;
|
||||||
|
|
||||||
|
const unsigned int RP1_PWM0_CHAN0_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*0+RP1_PWM0_CHAN_RANGE;
|
||||||
|
const unsigned int RP1_PWM0_CHAN1_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*1+RP1_PWM0_CHAN_RANGE;
|
||||||
|
const unsigned int RP1_PWM0_CHAN2_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*2+RP1_PWM0_CHAN_RANGE;
|
||||||
|
const unsigned int RP1_PWM0_CHAN3_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*3+RP1_PWM0_CHAN_RANGE;
|
||||||
|
|
||||||
|
const unsigned int RP1_PWM_CTRL_SETUPDATE = 0x80000000; // Bit 32
|
||||||
|
const unsigned int RP1_PWM_TRAIL_EDGE_MS = 0x1;
|
||||||
|
const unsigned int RP1_PWM_FIFO_POP_MASK = 0x100; // Bit 8
|
||||||
|
const unsigned int RP1_CLK_PWM0_CTRL_DISABLE_MAGIC = 0x10000000; // Default after boot
|
||||||
|
const unsigned int RP1_CLK_PWM0_CTRL_ENABLE_MAGIC = 0x11000840; // Reverse engineered, because of missing documentation, don't known meaning of of bits
|
||||||
|
|
||||||
|
const unsigned int CLK_PWM0_CTRL = (0x00074/4);
|
||||||
|
const unsigned int CLK_PWM0_DIV_INT = (0x00078/4);
|
||||||
|
const unsigned int CLK_PWM0_DIV_FRAC = (0x0007C/4);
|
||||||
|
const unsigned int CLK_PWM0_SEL = (0x00080/4);
|
||||||
|
|
||||||
//RP1 chip (@Pi5) address
|
//RP1 chip (@Pi5) address
|
||||||
const unsigned long long RP1_64_BASE_Addr = 0x1f000d0000;
|
const unsigned long long RP1_64_BASE_Addr = 0x1f000d0000;
|
||||||
const unsigned int RP1_BASE_Addr = 0x40000000;
|
const unsigned int RP1_BASE_Addr = 0x40000000;
|
||||||
const unsigned int RP1_PWM0_Addr = 0x40098000; // Adress is not mapped to gpiomem device!
|
const unsigned int RP1_CLOCK_Addr = 0x40018000; // Adress is not mapped to gpiomem device, lower than RP1_IO0_Addr
|
||||||
|
const unsigned int RP1_PWM0_Addr = 0x40098000; // Adress is not mapped to gpiomem device, lower than RP1_IO0_Addr
|
||||||
const unsigned int RP1_IO0_Addr = 0x400d0000;
|
const unsigned int RP1_IO0_Addr = 0x400d0000;
|
||||||
const unsigned int RP1_SYS_RIO0_Addr = 0x400e0000;
|
const unsigned int RP1_SYS_RIO0_Addr = 0x400e0000;
|
||||||
const unsigned int RP1_PADS0_Addr = 0x400f0000;
|
const unsigned int RP1_PADS0_Addr = 0x400f0000;
|
||||||
@@ -195,7 +231,7 @@ const unsigned short pciemem_RP1_Ventor= 0x1de4;
|
|||||||
const unsigned short pciemem_RP1_Device= 0x0001;
|
const unsigned short pciemem_RP1_Device= 0x0001;
|
||||||
|
|
||||||
static volatile unsigned int GPIO_PADS ;
|
static volatile unsigned int GPIO_PADS ;
|
||||||
static volatile unsigned int GPIO_CLOCK_BASE ;
|
static volatile unsigned int GPIO_CLOCK_ADR ;
|
||||||
static volatile unsigned int GPIO_BASE ;
|
static volatile unsigned int GPIO_BASE ;
|
||||||
static volatile unsigned int GPIO_TIMER ;
|
static volatile unsigned int GPIO_TIMER ;
|
||||||
static volatile unsigned int GPIO_PWM ;
|
static volatile unsigned int GPIO_PWM ;
|
||||||
@@ -241,6 +277,7 @@ static int wiringPiSetuped = FALSE ;
|
|||||||
const int PWMCLK_DIVI_MAX = 0xFFF; // 3 Byte max size for Clock devider
|
const int PWMCLK_DIVI_MAX = 0xFFF; // 3 Byte max size for Clock devider
|
||||||
const int OSC_FREQ_DEFAULT = 192; // x100kHz OSC
|
const int OSC_FREQ_DEFAULT = 192; // x100kHz OSC
|
||||||
const int OSC_FREQ_BCM2711 = 540; // x100kHz OSC
|
const int OSC_FREQ_BCM2711 = 540; // x100kHz OSC
|
||||||
|
const int OSC_FREQ_BCM2712 = 500; // x100kHz OSC - cat /sys/kernel/debug/clk/clk_summary | grep pwm0
|
||||||
|
|
||||||
// Timer
|
// Timer
|
||||||
// Word offsets
|
// Word offsets
|
||||||
@@ -589,10 +626,10 @@ int GetMaxPin() {
|
|||||||
|
|
||||||
#define RETURN_ON_MODEL5 if (PI_MODEL_5 == RaspberryPiModel) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; }
|
#define RETURN_ON_MODEL5 if (PI_MODEL_5 == RaspberryPiModel) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; }
|
||||||
|
|
||||||
int FailOnModel5() {
|
int FailOnModel5(const char *function) {
|
||||||
if (PI_MODEL_5 == RaspberryPiModel) {
|
if (PI_MODEL_5 == RaspberryPiModel) {
|
||||||
return wiringPiFailure (WPI_ALMOST, "Function not supported on Raspberry Pi 5.\n"
|
return wiringPiFailure (WPI_ALMOST, "Function '%s' not supported on Raspberry Pi 5.\n"
|
||||||
" Unable to continue. Keep an eye of new versions at https://github.com/wiringpi/wiringpi\n") ;
|
" Unable to continue. Keep an eye of new versions at https://github.com/wiringpi/wiringpi\n", function) ;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -715,8 +752,8 @@ static uint8_t gpioToPUDCLK [] =
|
|||||||
static uint8_t gpioToPwmALT [] =
|
static uint8_t gpioToPwmALT [] =
|
||||||
{
|
{
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
|
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
|
||||||
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15
|
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15
|
||||||
0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23
|
0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
|
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
|
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
|
||||||
FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47
|
FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47
|
||||||
@@ -731,8 +768,8 @@ static uint8_t gpioToPwmALT [] =
|
|||||||
static uint8_t gpioToPwmPort [] =
|
static uint8_t gpioToPwmPort [] =
|
||||||
{
|
{
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
|
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
|
||||||
0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15
|
0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15
|
||||||
0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23
|
0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
|
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
|
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
|
||||||
PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47
|
PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47
|
||||||
@@ -1287,7 +1324,7 @@ void setPadDrive (int group, int value)
|
|||||||
|
|
||||||
int getAlt (int pin)
|
int getAlt (int pin)
|
||||||
{
|
{
|
||||||
int fSel, shift, alt ;
|
int alt;
|
||||||
|
|
||||||
pin &= 63 ;
|
pin &= 63 ;
|
||||||
|
|
||||||
@@ -1318,29 +1355,28 @@ int getAlt (int pin)
|
|||||||
11 = alternate function 9
|
11 = alternate function 9
|
||||||
*/
|
*/
|
||||||
switch(alt) {
|
switch(alt) {
|
||||||
case 0: return 4;
|
case 0: return FSEL_ALT0;
|
||||||
case 1: return 5;
|
case 1: return FSEL_ALT1;
|
||||||
case 2: return 6;
|
case 2: return FSEL_ALT2;
|
||||||
case 3: return 7;
|
case 3: return FSEL_ALT3;
|
||||||
case 4: return 3;
|
case 4: return FSEL_ALT4;
|
||||||
case RP1_FSEL_GPIO: {
|
case RP1_FSEL_GPIO: {
|
||||||
unsigned int outputmask = gpio[2*pin] & 0x3000; //Bit13-OETOPAD + Bit12-OEFROMPERI
|
unsigned int outputmask = gpio[2*pin] & 0x3000; //Bit13-OETOPAD + Bit12-OEFROMPERI
|
||||||
return (outputmask==0x3000) ? 1 : 0; //1=OUT 0=IN
|
return (outputmask==0x3000) ? FSEL_OUTP : FSEL_INPT;
|
||||||
}
|
}
|
||||||
case 6: return 8;
|
case 6: return FSEL_ALT6;
|
||||||
case 7: return 9;
|
case 7: return FSEL_ALT7;
|
||||||
case 8: return 10;
|
case 8: return FSEL_ALT8;
|
||||||
case 9: return 11;
|
case RP1_FSEL_NONE: return FSEL_ALT9;
|
||||||
default:return alt;
|
default:return alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fSel = gpioToGPFSEL [pin] ;
|
int fSel = gpioToGPFSEL [pin] ;
|
||||||
shift = gpioToShift [pin] ;
|
int shift = gpioToShift [pin] ;
|
||||||
|
|
||||||
alt = (*(gpio + fSel) >> shift) & 7 ;
|
alt = (*(gpio + fSel) >> shift) & 7 ;
|
||||||
}
|
}
|
||||||
return alt ;
|
return alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1359,7 +1395,12 @@ void pwmSetMode (int mode)
|
|||||||
{
|
{
|
||||||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
|
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
|
||||||
{
|
{
|
||||||
FailOnModel5();
|
if (PI_MODEL_5 == RaspberryPiModel) {
|
||||||
|
if(mode != PWM_MODE_MS) {
|
||||||
|
fprintf(stderr, "pwmSetMode: Raspberry Pi 5 missing feature PWM BAL mode\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mode == PWM_MODE_MS) {
|
if (mode == PWM_MODE_MS) {
|
||||||
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ;
|
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ;
|
||||||
} else {
|
} else {
|
||||||
@@ -1381,7 +1422,6 @@ void pwmSetMode (int mode)
|
|||||||
|
|
||||||
void pwmSetRange (unsigned int range)
|
void pwmSetRange (unsigned int range)
|
||||||
{
|
{
|
||||||
FailOnModel5();
|
|
||||||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
|
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
|
||||||
{
|
{
|
||||||
/* would be possible on ms mode but not on bal, deactivated, use pwmc modify instead
|
/* would be possible on ms mode but not on bal, deactivated, use pwmc modify instead
|
||||||
@@ -1389,10 +1429,24 @@ void pwmSetRange (unsigned int range)
|
|||||||
range = (OSC_FREQ_BCM2711*range)/OSC_FREQ_DEFAULT;
|
range = (OSC_FREQ_BCM2711*range)/OSC_FREQ_DEFAULT;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ;
|
if (!pwm) {
|
||||||
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ;
|
fprintf(stderr, "wiringPi: pwmSetRange but no pwm memory available, ignoring\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int readback = 0x00;
|
||||||
|
if (PI_MODEL_5 == RaspberryPiModel) {
|
||||||
|
pwm[RP1_PWM0_CHAN0_RANGE] = range;
|
||||||
|
pwm[RP1_PWM0_CHAN1_RANGE] = range;
|
||||||
|
pwm[RP1_PWM0_CHAN2_RANGE] = range;
|
||||||
|
pwm[RP1_PWM0_CHAN3_RANGE] = range;
|
||||||
|
readback = pwm[RP1_PWM0_CHAN0_RANGE];
|
||||||
|
} else {
|
||||||
|
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ;
|
||||||
|
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ;
|
||||||
|
readback = *(pwm + PWM0_RANGE);
|
||||||
|
}
|
||||||
if (wiringPiDebug) {
|
if (wiringPiDebug) {
|
||||||
printf ("PWM range: %u. Current register: 0x%08X\n", range, *(pwm + PWM0_RANGE));
|
printf ("PWM range: %u. Current register: 0x%08X\n", range, readback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1409,20 +1463,40 @@ void pwmSetRange (unsigned int range)
|
|||||||
void pwmSetClock (int divisor)
|
void pwmSetClock (int divisor)
|
||||||
{
|
{
|
||||||
uint32_t pwm_control ;
|
uint32_t pwm_control ;
|
||||||
|
if (!clk) {
|
||||||
|
fprintf(stderr, "wiringPi: pwmSetClock but no clk memory available, ignoring\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FailOnModel5();
|
if (divisor > PWMCLK_DIVI_MAX) {
|
||||||
|
divisor = PWMCLK_DIVI_MAX; // even on Pi5 4095 is OK
|
||||||
|
}
|
||||||
|
if (PI_MODEL_5 == RaspberryPiModel) {
|
||||||
|
if (divisor < 1) {
|
||||||
|
if (wiringPiDebug) { printf("Disable PWM0 clock"); }
|
||||||
|
clk[CLK_PWM0_CTRL] = RP1_CLK_PWM0_CTRL_DISABLE_MAGIC; // 0 = disable on Pi5
|
||||||
|
} else {
|
||||||
|
divisor = (OSC_FREQ_BCM2712*divisor)/OSC_FREQ_DEFAULT;
|
||||||
|
if (wiringPiDebug) {
|
||||||
|
printf ("PWM clock divisor: %d\n", divisor) ;
|
||||||
|
}
|
||||||
|
//clk[CLK_PWM0_CTRL] = RP1_CLK_PWM0_CTRL_DISABLE_MAGIC;
|
||||||
|
//delayMicroseconds(100);
|
||||||
|
clk[CLK_PWM0_DIV_INT] = divisor;
|
||||||
|
clk[CLK_PWM0_DIV_FRAC] = 0;
|
||||||
|
clk[CLK_PWM0_SEL] = 1;
|
||||||
|
clk[CLK_PWM0_CTRL] = RP1_CLK_PWM0_CTRL_ENABLE_MAGIC;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (piGpioBase == GPIO_PERI_BASE_2711) {
|
if (piGpioBase == GPIO_PERI_BASE_2711) {
|
||||||
//calculate value for OSC 54MHz -> 19.2MHz
|
//calculate value for OSC 54MHz -> 19.2MHz
|
||||||
// Pi 4 max divisor is 1456, Pi0-3 is 4095 (0xFFF)
|
// Pi 4 max divisor is 1456, Pi0-3 is 4095 (0xFFF)
|
||||||
divisor = (OSC_FREQ_BCM2711*divisor)/OSC_FREQ_DEFAULT;
|
divisor = (OSC_FREQ_BCM2711*divisor)/OSC_FREQ_DEFAULT;
|
||||||
}
|
}
|
||||||
if (divisor > PWMCLK_DIVI_MAX) {
|
|
||||||
divisor = PWMCLK_DIVI_MAX;
|
|
||||||
}
|
|
||||||
if (divisor < 1) {
|
if (divisor < 1) {
|
||||||
divisor = 1;
|
divisor = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
|
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
|
||||||
{
|
{
|
||||||
if (wiringPiDebug) {
|
if (wiringPiDebug) {
|
||||||
@@ -1469,7 +1543,7 @@ void gpioClockSet (int pin, int freq)
|
|||||||
{
|
{
|
||||||
int divi, divr, divf ;
|
int divi, divr, divf ;
|
||||||
|
|
||||||
FailOnModel5();
|
FailOnModel5("gpioClockSet");
|
||||||
pin &= 63 ;
|
pin &= 63 ;
|
||||||
|
|
||||||
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
||||||
@@ -1658,9 +1732,6 @@ int requestLine(int pin, unsigned int lineRequestFlags) {
|
|||||||
|
|
||||||
void pinModeAlt (int pin, int mode)
|
void pinModeAlt (int pin, int mode)
|
||||||
{
|
{
|
||||||
int fSel, shift ;
|
|
||||||
|
|
||||||
RETURN_ON_MODEL5
|
|
||||||
setupCheck ("pinModeAlt") ;
|
setupCheck ("pinModeAlt") ;
|
||||||
|
|
||||||
if ((pin & PI_GPIO_MASK) == 0) // On-board pin
|
if ((pin & PI_GPIO_MASK) == 0) // On-board pin
|
||||||
@@ -1673,20 +1744,49 @@ void pinModeAlt (int pin, int mode)
|
|||||||
return ;
|
return ;
|
||||||
|
|
||||||
if (PI_MODEL_5 == RaspberryPiModel) {
|
if (PI_MODEL_5 == RaspberryPiModel) {
|
||||||
|
|
||||||
//confusion! diffrent to to BCM! this is taking directly the value for the register
|
//confusion! diffrent to to BCM! this is taking directly the value for the register
|
||||||
/*
|
int modeRP1;
|
||||||
"alt0" 0b100
|
switch(mode) {
|
||||||
"alt1" 0b101
|
case FSEL_ALT0:
|
||||||
"alt2" 0b110
|
modeRP1 = 0;
|
||||||
"alt3" 0b111
|
break;
|
||||||
"alt4" 0b011
|
case FSEL_ALT1:
|
||||||
"alt5" 0b010
|
modeRP1 = 1;
|
||||||
*/
|
break;
|
||||||
gpio[2*pin+1] = (mode & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time
|
case FSEL_ALT2:
|
||||||
|
modeRP1 = 2;
|
||||||
|
break;
|
||||||
|
case FSEL_ALT3:
|
||||||
|
modeRP1 = 3;
|
||||||
|
break;
|
||||||
|
case FSEL_ALT4:
|
||||||
|
modeRP1 = 4;
|
||||||
|
break;
|
||||||
|
case FSEL_ALT5:
|
||||||
|
modeRP1 = 5;
|
||||||
|
break;
|
||||||
|
case FSEL_ALT6:
|
||||||
|
modeRP1 = 6;
|
||||||
|
break;
|
||||||
|
case FSEL_ALT7:
|
||||||
|
modeRP1 = 7;
|
||||||
|
break;
|
||||||
|
case FSEL_ALT8:
|
||||||
|
modeRP1 = 8;
|
||||||
|
break;
|
||||||
|
case FSEL_OUTP:
|
||||||
|
case FSEL_INPT:
|
||||||
|
modeRP1 = RP1_FSEL_GPIO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "pinModeAlt: invalid mode %d\n", mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//printf("pinModeAlt: Pi5 alt pin %d to %d\n", pin, modeRP1);
|
||||||
|
gpio[2*pin+1] = (modeRP1 & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time
|
||||||
} else {
|
} else {
|
||||||
fSel = gpioToGPFSEL [pin] ;
|
int fSel = gpioToGPFSEL [pin] ;
|
||||||
shift = gpioToShift [pin] ;
|
int shift = gpioToShift [pin] ;
|
||||||
|
|
||||||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ;
|
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ;
|
||||||
}
|
}
|
||||||
@@ -1794,8 +1894,14 @@ void pinMode (int pin, int mode)
|
|||||||
} else {
|
} else {
|
||||||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
|
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
|
||||||
}
|
}
|
||||||
if (PM_OFF==mode && !usingGpioMem && pwm && PI_MODEL_5!=RaspberryPiModel && gpioToPwmALT[pin]>0) { //PWM pin -> reset
|
if (PM_OFF==mode && !usingGpioMem && pwm && gpioToPwmALT[pin]>0) { //PWM pin -> reset
|
||||||
pwmWrite(origPin, 0);
|
pwmWrite(origPin, 0);
|
||||||
|
int channel = gpioToPwmPort[pin];
|
||||||
|
if (channel>=0 && channel<=3 && PI_MODEL_5 == RaspberryPiModel) {
|
||||||
|
unsigned int ctrl = pwm[RP1_PWM0_GLOBAL_CTRL];
|
||||||
|
pwm[RP1_PWM0_GLOBAL_CTRL] = (ctrl & ~(1<<channel)) | RP1_PWM_CTRL_SETUPDATE;
|
||||||
|
//printf("Disable PWM0[%d] (0x%08X->0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (mode == OUTPUT) {
|
} else if (mode == OUTPUT) {
|
||||||
if (PI_MODEL_5 == RaspberryPiModel) {
|
if (PI_MODEL_5 == RaspberryPiModel) {
|
||||||
@@ -1815,20 +1921,35 @@ void pinMode (int pin, int mode)
|
|||||||
pwmSetMode (PWM_MODE_MS) ;
|
pwmSetMode (PWM_MODE_MS) ;
|
||||||
}
|
}
|
||||||
else if (PWM_OUTPUT==mode || PWM_MS_OUTPUT==mode || PWM_BAL_OUTPUT==mode) {
|
else if (PWM_OUTPUT==mode || PWM_MS_OUTPUT==mode || PWM_BAL_OUTPUT==mode) {
|
||||||
RETURN_ON_MODEL5
|
|
||||||
if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin
|
|
||||||
return ;
|
|
||||||
|
|
||||||
usingGpioMemCheck("pinMode PWM") ; // exit on error!
|
usingGpioMemCheck("pinMode PWM") ; // exit on error!
|
||||||
|
alt = gpioToPwmALT[pin];
|
||||||
// Set pin to PWM mode
|
if (0==alt) { // Not a hardware capable PWM pin
|
||||||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
|
return;
|
||||||
delayMicroseconds (110) ; // See comments in pwmSetClockWPi
|
}
|
||||||
|
int channel = gpioToPwmPort[pin];
|
||||||
if (PWM_OUTPUT==mode || PWM_BAL_OUTPUT==mode) {
|
if (PI_MODEL_5 == RaspberryPiModel) {
|
||||||
pwmSetMode(PWM_MODE_BAL); // Pi default mode
|
if (channel>=0 && channel<=3) {
|
||||||
|
// enable channel pwm m:s mode
|
||||||
|
pwm[RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*channel+RP1_PWM0_CHAN_CTRL] = (RP1_PWM_TRAIL_EDGE_MS | RP1_PWM_FIFO_POP_MASK);
|
||||||
|
// enable pwm global
|
||||||
|
unsigned int ctrl = pwm[RP1_PWM0_GLOBAL_CTRL];
|
||||||
|
pwm[RP1_PWM0_GLOBAL_CTRL] = ctrl | (1<<channel) | RP1_PWM_CTRL_SETUPDATE;
|
||||||
|
//printf("Enable PWM0[%d] (0x%08X->0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]);
|
||||||
|
//change GPIO mode
|
||||||
|
pads[1+pin] = RP1_PAD_DEFAULT_FROM9; // enable output
|
||||||
|
pinModeAlt(origPin, alt); //switch to PWM mode
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pwmSetMode(PWM_MODE_MS);
|
// Set pin to PWM mode
|
||||||
|
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
|
||||||
|
delayMicroseconds (110) ; // See comments in pwmSetClockWPi
|
||||||
|
|
||||||
|
if (PWM_OUTPUT==mode || PWM_BAL_OUTPUT==mode) {
|
||||||
|
pwmSetMode(PWM_MODE_BAL); // Pi default mode
|
||||||
|
} else {
|
||||||
|
pwmSetMode(PWM_MODE_MS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (PWM_OUTPUT==mode) { // predefine
|
if (PWM_OUTPUT==mode) { // predefine
|
||||||
pwmSetRange (1024) ; // Default range of 1024
|
pwmSetRange (1024) ; // Default range of 1024
|
||||||
@@ -2173,7 +2294,6 @@ void pwmWrite (int pin, int value)
|
|||||||
{
|
{
|
||||||
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
||||||
|
|
||||||
FailOnModel5();
|
|
||||||
setupCheck ("pwmWrite") ;
|
setupCheck ("pwmWrite") ;
|
||||||
|
|
||||||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
||||||
@@ -2191,9 +2311,22 @@ void pwmWrite (int pin, int value)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
usingGpioMemCheck ("pwmWrite") ;
|
usingGpioMemCheck ("pwmWrite") ;
|
||||||
*(pwm + gpioToPwmPort [pin]) = value ;
|
int channel = gpioToPwmPort[pin];
|
||||||
|
int readback = 0x00;
|
||||||
|
if (PI_MODEL_5 == RaspberryPiModel ) {
|
||||||
|
if (channel>=0 && channel<=3) {
|
||||||
|
unsigned int addr = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*channel+RP1_PWM0_CHAN_DUTY;
|
||||||
|
pwm[addr] = value;
|
||||||
|
readback = pwm[addr];
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "pwmWrite: invalid channel at GPIO pin %d \n", pin);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*(pwm + channel) = value ;
|
||||||
|
readback = *(pwm + channel);
|
||||||
|
}
|
||||||
if (wiringPiDebug) {
|
if (wiringPiDebug) {
|
||||||
printf ("PWM value: %u. Current register: 0x%08X\n", value, *(pwm + gpioToPwmPort[pin]));
|
printf ("PWM value(duty): %u. Current register: 0x%08X\n", value, readback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2251,8 +2384,6 @@ void analogWrite (int pin, int value)
|
|||||||
|
|
||||||
void pwmToneWrite (int pin, int freq)
|
void pwmToneWrite (int pin, int freq)
|
||||||
{
|
{
|
||||||
FailOnModel5();
|
|
||||||
|
|
||||||
setupCheck ("pwmToneWrite") ;
|
setupCheck ("pwmToneWrite") ;
|
||||||
|
|
||||||
if (freq == 0)
|
if (freq == 0)
|
||||||
@@ -2290,7 +2421,7 @@ void digitalWriteByte (const int value)
|
|||||||
int mask = 1 ;
|
int mask = 1 ;
|
||||||
int pin ;
|
int pin ;
|
||||||
|
|
||||||
FailOnModel5();
|
FailOnModel5("digitalWriteByte");
|
||||||
|
|
||||||
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
||||||
{
|
{
|
||||||
@@ -2319,7 +2450,7 @@ unsigned int digitalReadByte (void)
|
|||||||
uint32_t raw ;
|
uint32_t raw ;
|
||||||
uint32_t data = 0 ;
|
uint32_t data = 0 ;
|
||||||
|
|
||||||
FailOnModel5();
|
FailOnModel5("digitalReadByte");
|
||||||
|
|
||||||
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
||||||
{
|
{
|
||||||
@@ -2350,7 +2481,7 @@ unsigned int digitalReadByte (void)
|
|||||||
|
|
||||||
void digitalWriteByte2 (const int value)
|
void digitalWriteByte2 (const int value)
|
||||||
{
|
{
|
||||||
FailOnModel5();
|
FailOnModel5("digitalWriteByte2");
|
||||||
|
|
||||||
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
||||||
{
|
{
|
||||||
@@ -2366,7 +2497,7 @@ unsigned int digitalReadByte2 (void)
|
|||||||
{
|
{
|
||||||
uint32_t data = 0 ;
|
uint32_t data = 0 ;
|
||||||
|
|
||||||
FailOnModel5();
|
FailOnModel5("digitalReadByte2");
|
||||||
|
|
||||||
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
||||||
{
|
{
|
||||||
@@ -2937,6 +3068,17 @@ int wiringPiSetup (void)
|
|||||||
if (PI_MODEL_5 == model) {
|
if (PI_MODEL_5 == model) {
|
||||||
gpiomemGlobal = pciemem_RP1;
|
gpiomemGlobal = pciemem_RP1;
|
||||||
gpiomemModule = gpiomem_RP1;
|
gpiomemModule = gpiomem_RP1;
|
||||||
|
|
||||||
|
// PWM alt pins @RP1 - need to be translated to RP1_FSEL with pinModeAlt
|
||||||
|
gpioToPwmALT[12] = FSEL_ALT0;
|
||||||
|
gpioToPwmALT[13] = FSEL_ALT0;
|
||||||
|
gpioToPwmALT[18] = FSEL_ALT3;
|
||||||
|
gpioToPwmALT[19] = FSEL_ALT3;
|
||||||
|
//PWM0 channel @RP1
|
||||||
|
gpioToPwmPort[12] = 0;
|
||||||
|
gpioToPwmPort[13] = 1;
|
||||||
|
gpioToPwmPort[18] = 2;
|
||||||
|
gpioToPwmPort[19] = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
usingGpioMem = FALSE;
|
usingGpioMem = FALSE;
|
||||||
@@ -2963,10 +3105,10 @@ int wiringPiSetup (void)
|
|||||||
if (PI_MODEL_5 != model) {
|
if (PI_MODEL_5 != model) {
|
||||||
//Set the offsets into the memory interface.
|
//Set the offsets into the memory interface.
|
||||||
|
|
||||||
GPIO_PADS = piGpioBase + 0x00100000 ;
|
GPIO_PADS = piGpioBase + 0x00100000 ;
|
||||||
GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ;
|
GPIO_CLOCK_ADR = piGpioBase + 0x00101000 ;
|
||||||
GPIO_BASE = piGpioBase + 0x00200000 ;
|
GPIO_BASE = piGpioBase + 0x00200000 ;
|
||||||
GPIO_TIMER = piGpioBase + 0x0000B000 ;
|
GPIO_TIMER = piGpioBase + 0x0000B000 ;
|
||||||
GPIO_PWM = piGpioBase + 0x0020C000 ;
|
GPIO_PWM = piGpioBase + 0x0020C000 ;
|
||||||
GPIO_RIO = 0x00 ;
|
GPIO_RIO = 0x00 ;
|
||||||
|
|
||||||
@@ -2986,7 +3128,7 @@ int wiringPiSetup (void)
|
|||||||
|
|
||||||
// Clock control (needed for PWM)
|
// Clock control (needed for PWM)
|
||||||
|
|
||||||
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ;
|
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_ADR) ;
|
||||||
if (clk == MAP_FAILED)
|
if (clk == MAP_FAILED)
|
||||||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ;
|
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ;
|
||||||
|
|
||||||
@@ -3022,7 +3164,7 @@ int wiringPiSetup (void)
|
|||||||
unsigned int MMAP_size = (usingGpioMem) ? gpiomem_RP1_Size : pciemem_RP1_Size;
|
unsigned int MMAP_size = (usingGpioMem) ? gpiomem_RP1_Size : pciemem_RP1_Size;
|
||||||
|
|
||||||
GPIO_PADS = (RP1_PADS0_Addr-RP1_IO0_Addr) ;
|
GPIO_PADS = (RP1_PADS0_Addr-RP1_IO0_Addr) ;
|
||||||
GPIO_CLOCK_BASE = 0x00;
|
GPIO_CLOCK_ADR = (RP1_CLOCK_Addr-RP1_BASE_Addr);
|
||||||
GPIO_BASE = (RP1_IO0_Addr-RP1_BASE_Addr) ;
|
GPIO_BASE = (RP1_IO0_Addr-RP1_BASE_Addr) ;
|
||||||
GPIO_TIMER = 0x00;
|
GPIO_TIMER = 0x00;
|
||||||
GPIO_PWM = RP1_PWM0_Addr-RP1_BASE_Addr;
|
GPIO_PWM = RP1_PWM0_Addr-RP1_BASE_Addr;
|
||||||
@@ -3034,8 +3176,12 @@ int wiringPiSetup (void)
|
|||||||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
|
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
|
||||||
if (usingGpioMem) {
|
if (usingGpioMem) {
|
||||||
gpio = base; // RP1 start adress of map memory for gpio (same as module memory)
|
gpio = base; // RP1 start adress of map memory for gpio (same as module memory)
|
||||||
|
pwm = NULL; // outside of mapped memory, PWM not available from none root
|
||||||
|
clk = NULL; // outside of mapped memory, CLK main not available from none root
|
||||||
} else {
|
} else {
|
||||||
gpio = &base[GPIO_BASE/4];// RP1 start adress of map memory for gpio
|
gpio = &base[GPIO_BASE/4]; // RP1 start adress of map memory for gpio
|
||||||
|
pwm = &base[GPIO_PWM/4]; // RP1 start adress of map memory for pwm0
|
||||||
|
clk = &base[GPIO_CLOCK_ADR/4]; // RP1 start adress of map memory for clocks_main
|
||||||
}
|
}
|
||||||
pads = &gpio[GPIO_PADS/4]; // RP1 start adress of map memory for pads
|
pads = &gpio[GPIO_PADS/4]; // RP1 start adress of map memory for pads
|
||||||
rio = &gpio[GPIO_RIO/4]; // RP1 start adress of map memory for rio
|
rio = &gpio[GPIO_RIO/4]; // RP1 start adress of map memory for rio
|
||||||
@@ -3045,19 +3191,19 @@ int wiringPiSetup (void)
|
|||||||
// Export the base addresses for any external software that might need them
|
// Export the base addresses for any external software that might need them
|
||||||
_wiringPiBase = base ;
|
_wiringPiBase = base ;
|
||||||
_wiringPiGpio = gpio ;
|
_wiringPiGpio = gpio ;
|
||||||
_wiringPiPwm = NULL ;
|
_wiringPiPwm = pwm ;
|
||||||
_wiringPiClk = NULL ;
|
_wiringPiClk = clk ;
|
||||||
_wiringPiPads = pads ;
|
_wiringPiPads = pads ;
|
||||||
_wiringPiTimer = NULL ;
|
_wiringPiTimer = NULL ;
|
||||||
_wiringPiRio = rio ;
|
_wiringPiRio = rio ;
|
||||||
}
|
}
|
||||||
if (wiringPiDebug) {
|
if (wiringPiDebug) {
|
||||||
printf ("wiringPi: memory map gpio 0x%x %s\n", GPIO_BASE , _wiringPiGpio ? "valid" : "invalid");
|
printf ("wiringPi: memory map gpio 0x%x %s\n", GPIO_BASE , _wiringPiGpio ? "valid" : "invalid");
|
||||||
printf ("wiringPi: memory map pads 0x%x %s\n", GPIO_PADS , _wiringPiPads ? "valid" : "invalid");
|
printf ("wiringPi: memory map pads 0x%x %s\n", GPIO_PADS , _wiringPiPads ? "valid" : "invalid");
|
||||||
printf ("wiringPi: memory map rio 0x%x %s\n", GPIO_RIO , _wiringPiRio ? "valid" : "invalid");
|
printf ("wiringPi: memory map rio 0x%x %s\n", GPIO_RIO , _wiringPiRio ? "valid" : "invalid");
|
||||||
printf ("wiringPi: memory map pwm 0x%x %s\n", GPIO_PWM , _wiringPiPwm ? "valid" : "invalid");
|
printf ("wiringPi: memory map pwm0 0x%x %s\n", GPIO_PWM , _wiringPiPwm ? "valid" : "invalid");
|
||||||
printf ("wiringPi: memory map clk 0x%x %s\n", GPIO_CLOCK_BASE, _wiringPiClk ? "valid" : "invalid");
|
printf ("wiringPi: memory map clocks 0x%x %s\n", GPIO_CLOCK_ADR, _wiringPiClk ? "valid" : "invalid");
|
||||||
printf ("wiringPi: memory map timer 0x%x %s\n", GPIO_TIMER,_wiringPiTimer ? "valid" : "invalid");
|
printf ("wiringPi: memory map timer 0x%x %s\n", GPIO_TIMER ,_wiringPiTimer ? "valid" : "invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
initialiseEpoch () ;
|
initialiseEpoch () ;
|
||||||
|
|||||||
Reference in New Issue
Block a user