New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hardware PMW function not working on Pi4B revision 1.4 #517
Comments
Right, mine are revision 1.1 Oddly, one of the first searches I hit on rev 1.4 turned up an article about the changes having something to do with the USB-C interface confusing the root hub that it was an audio device. Perhaps we should ask the OP of they can try a generic/dumb USB-C cable (as opposed to the electronically marked or e-marked USB-C cable variety). |
OP here. I ran the v79 as requested by Joan, with all tests passing except for one in The cable we use is as dumb as it gets: a USB-C cable with only the +5V and GND wires connected to a dedicated 5V, 10A PSU (Mean Well MPM-65-5ST). We never had any power/throttling issues with this one. We may be able to help with testing. We have a single rev 1.1, and a bunch of rev 1.2 and rev 1.4 boards, as well as CM4s + IO board. Let me know if there's anything you want us to check. The board I used for testing has 2711ZPKFSB06C0T type indicator on the CPU cover. From Googling this seems to indicate a C0 stepping. |
Stranger and stranger. The default tests use the PCM peripheral to pace DMA for GPIO sampling but will use the PWM peripheral for waves. So the PWM peripheral is working to an extent. Could you possibly do another test as follows.
|
Sure. Same error (ERROR: No more CBs for waveform) Full results: pigpio-v79-pi4b-rev14-tests-v2.txt |
Interesting. Be patient for a quarter hour or so. I have another test in mind. |
Could you run the following Python with the normal daemon.
import pigpio
import time
G=12
TEST_TIME=5
pi = pigpio.pi()
if not pi.connected:
exit()
cb = pi.callback(G)
for freq in [1, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000]:
pi.hardware_PWM(G, freq, 500000)
cb.reset_tally()
time.sleep(TEST_TIME)
print(freq, cb.tally()/TEST_TIME)
pi.stop() |
Sure, results here:
|
The results for the 20k freq look strange. Ran the test again, same results:
Will try these on a rev12 board as well and report back |
Odder and odder. That looks okay apart from 20 kHz which seems to be wrong. Could you try with GPIO 13 (rather than 12). |
Rev 12 results (still with GPIO 12):
Will try with GPIO 13 in a minute on both revisions |
GPIO 13 looks ok on both rev 1.2 and rev 1.4:
|
Ran the tests on a rev 1.1 as well, with similar results as the rev 1.2 (both GPIO 12 and 13 work as expected) |
Odd and odder. For your use could you use GPIO13 or GPIO19 rather than GPIO12? Might be a temporary fix. |
I'm discussing the use of GPIO13 with my team. Meanwhile I'm trying to pinpoint the starting/end frequencies of this strange behaviour. I'm still narrowing it down, but it looks like it's not just 20Khz, more like 11Khz-45Khz. |
It could perhaps be related to audio, looking at these frequencies? |
When you do the tests do you use the same SD card in each Pi and do they have the same peripherals connected? We have had odd results before but never managed to identify a reason or pattern. |
On the rev11 and rev12 Pi's I used an existing os installation, on both devices with different peripherals connected. On the rev14 Pi I used in the above test I've disconnected all peripherals before testing, except for a Raspberry pi 7" touchscreen and ethernet cable. |
Regarding the start / end frequencies:
|
Thanks for that. Does seem suspiciously like audio. Guy and myself will have to give this some thought. We probably do need input from the Foundation unless we find some queer bug in our code. |
I'll run a few more tests to try to figure out which models (Model 4B & CM4) & OS combinations are affected. And ask if we can get some assistance from the Foundation for this issue. It looks like we have to create and produce a revision of our pcb to use GPIO 13, which would delay things on our end quite a bit. A workaround or fix would be most helpful. I'll also have a look if disabling audio will have any effect. |
And thanks for the support so far, Joan & Guy! Much appreciated! |
This is an expected, good, result from the test. I was lazy and never went back in the code to suppress it. Please ignore.
I believe we have seen HDMI connections turn audio on in some configurations and cause conflict with pigpio. Could you run the rev 1.4 units headless just be verify this is not a factor? |
I've disconnected the DSI cable so the rev 1.4 test pi is now fully headless (with both Wifi & ethernet connected). The results are slightly different, now also giving problems at 10khz:
|
Note to ourselves: C0 has changes allowing DMA to access greater memory ranges. Hopefully firmware APIs did not change. |
Ran above |
I've tested the issue with the Rev 1.4 Pi on all four latest OS builds (32/64-bit, Buster/Bullseye) using a slightly modified test_hp.py script. Same results, with varying frequency ranges that show the anomaly. I will check on the CM4 next. Logs: Note that hardware is reported as BCM2835 in the 64-bit builds test_hp.py modified: import pigpio
import time
G=12
TEST_TIME=5
pi = pigpio.pi()
if not pi.connected:
exit()
cb = pi.callback(G)
def test(freq):
pi.hardware_PWM(G, freq, 500000)
cb.reset_tally()
time.sleep(TEST_TIME)
print(freq, cb.tally()/TEST_TIME)
print("Basic test:")
for freq in [1, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000]:
test(freq)
print("\nFinding start:")
for freq in range(5000, 12000, 200):
test(freq)
print("\nFinding end:")
for freq in range(43000, 48000, 200):
test(freq)
pi.stop() |
Thank you @martijnt , but I think it is pointing to pigpio on C0 step. |
@joan2937 , please checkout this post from raspberrypi.stackexchange.com To fix their u-boot issue, they had to change the virtual address of the XHCI PCI device! (see link to patch). |
The CM4 rev 1.0 has the issue too. This one also has a C0 stepping (same type number on the SOC). |
Unfortunately, I was a bit too quick to say GPIO13 is ok. I was focusing on the 20Khz counter, but overlooked 50Khz. If you look at the results for the test with GPIO13 on the rev14 above, you'll notice 50Khz is off as well (the counter is at 33k). I've repeated this test a couple of times this morning, and getting similar results (counter at 5854 in one test, 7691 in another). I've run the test in the range our fans support [20khz-28khz], and it starts breaking down at around 23Khz:
|
Next, I noticed that when switching between windows - terminal (showing pigs) and a browser - the waveform momentarily becomes stable then erratic again. [EDIT] I'm using a Pi400. I've disconnected the monitor, rebooted and then ssh'ed in from a remote pc. Now my scope never syncs to the 10KHz waveform. 1KHz, however, is stable. So, I believe this test is validating what |
I am using the following rather messy code (a merge of minimal gpio access and the hardware PWM code). The oddity boundaries seem to be associated with range and/or dutycycle (as set in the PWM hardware) being powers of 2. $ sudo ./hwpwm 45780 12 500000 $ sudo ./hwpwm 45779 12 500000 Early days, but I'm sure there is a pattern. Getting more convinced the hardware is broken. /*
hwpwm.c
2022-02-11
Public Domain
*/
/*
gcc -o hwpwm hwpwm.c
sudo ./hwpwm
*/
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#define BCM_PASSWD (0x5A<<24)
#define CLK_CTL_MASH(x)((x)<<9)
#define CLK_CTL_BUSY (1 <<7)
#define CLK_CTL_KILL (1 <<5)
#define CLK_CTL_ENAB (1 <<4)
#define CLK_CTL_SRC(x) ((x)<<0)
#define CLK_SRCS 2
#define CLK_CTL_SRC_OSC 1
#define CLK_CTL_SRC_PLLD 6
#define CLK_OSC_FREQ 19200000
#define CLK_OSC_FREQ_2711 54000000
#define CLK_PLLD_FREQ 500000000
#define CLK_PLLD_FREQ_2711 750000000
#define CLK_DIV_DIVI(x) ((x)<<12)
#define CLK_DIV_DIVF(x) ((x)<< 0)
#define CLK_GP0_CTL 28
#define CLK_GP0_DIV 29
#define CLK_GP1_CTL 30
#define CLK_GP1_DIV 31
#define CLK_GP2_CTL 32
#define CLK_GP2_DIV 33
#define CLK_PCMCTL 38
#define CLK_PCMDIV 39
#define CLK_PWMCTL 40
#define CLK_PWMDIV 41
#define PWM_CTL 0
#define PWM_STA 1
#define PWM_DMAC 2
#define PWM_RNG1 4
#define PWM_DAT1 5
#define PWM_FIFO 6
#define PWM_RNG2 8
#define PWM_DAT2 9
#define PWM_CTL_MSEN2 (1<<15)
#define PWM_CTL_PWEN2 (1<<8)
#define PWM_CTL_MSEN1 (1<<7)
#define PWM_CTL_CLRF1 (1<<6)
#define PWM_CTL_USEF1 (1<<5)
#define PWM_CTL_MODE1 (1<<1)
#define PWM_CTL_PWEN1 (1<<0)
#define PI_HW_PWM_MAX_FREQ 125000000
#define PI_HW_PWM_MAX_FREQ_2711 187500000
#define CLK_PLLD_FREQ 500000000
#define CLK_PLLD_FREQ_2711 750000000
#define PI_HW_PWM_RANGE 1000000
static uint32_t piPeriphBase = 0x20000000;
static volatile int pi_is_2711 = 0;
static volatile uint32_t * clkReg = MAP_FAILED;
static volatile uint32_t hw_pwm_max_freq = PI_HW_PWM_MAX_FREQ;
static volatile uint32_t clk_plld_freq = CLK_PLLD_FREQ_2711;
static uint32_t hw_pwm_freq[2];
static uint32_t hw_pwm_duty[2];
static uint32_t hw_pwm_real_range[2];
static const uint8_t PWMDef[54] =
{
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 1 */ 0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92,
/* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 4 */ 0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00,
/* 5 */ 0x00, 0x00, 0x85, 0x95,
};
#define SYST_BASE (piPeriphBase + 0x003000)
#define DMA_BASE (piPeriphBase + 0x007000)
#define CLK_BASE (piPeriphBase + 0x101000)
#define GPIO_BASE (piPeriphBase + 0x200000)
#define UART0_BASE (piPeriphBase + 0x201000)
#define PCM_BASE (piPeriphBase + 0x203000)
#define SPI0_BASE (piPeriphBase + 0x204000)
#define I2C0_BASE (piPeriphBase + 0x205000)
#define PWM_BASE (piPeriphBase + 0x20C000)
#define BSCS_BASE (piPeriphBase + 0x214000)
#define UART1_BASE (piPeriphBase + 0x215000)
#define I2C1_BASE (piPeriphBase + 0x804000)
#define I2C2_BASE (piPeriphBase + 0x805000)
#define DMA15_BASE (piPeriphBase + 0xE05000)
#define DMA_LEN 0x1000 /* allow access to all channels */
#define CLK_LEN 0xA8
#define GPIO_LEN 0xF4
#define SYST_LEN 0x1C
#define PCM_LEN 0x24
#define PWM_LEN 0x28
#define I2C_LEN 0x1C
#define BSCS_LEN 0x40
#define GPSET0 7
#define GPSET1 8
#define GPCLR0 10
#define GPCLR1 11
#define GPLEV0 13
#define GPLEV1 14
#define GPPUD 37
#define GPPUDCLK0 38
#define GPPUDCLK1 39
/* BCM2711 has different pulls */
#define GPPUPPDN0 57
#define GPPUPPDN1 58
#define GPPUPPDN2 59
#define GPPUPPDN3 60
#define SYST_CS 0
#define SYST_CLO 1
#define SYST_CHI 2
static volatile uint32_t *gpioReg = MAP_FAILED;
static volatile uint32_t *pwmReg = MAP_FAILED;
static volatile uint32_t *systReg = MAP_FAILED;
#define PI_BANK (gpio>>5)
#define PI_BIT (1<<(gpio&0x1F))
/* gpio modes. */
#define PI_INPUT 0
#define PI_OUTPUT 1
#define PI_ALT0 4
#define PI_ALT1 5
#define PI_ALT2 6
#define PI_ALT3 7
#define PI_ALT4 3
#define PI_ALT5 2
static void initHWClk
(int clkCtl, int clkDiv, int clkSrc, int divI, int divF, int MASH)
{
printf("ctl=%d div=%d src=%d /I=%d /f=%d M=%d\n",
clkCtl, clkDiv, clkSrc, divI, divF, MASH);
/* kill the clock if busy, anything else isn't reliable */
if (clkReg[clkCtl] & CLK_CTL_BUSY)
{
do
{
clkReg[clkCtl] = BCM_PASSWD | CLK_CTL_KILL;
}
while (clkReg[clkCtl] & CLK_CTL_BUSY);
}
clkReg[clkDiv] = (BCM_PASSWD | CLK_DIV_DIVI(divI) | CLK_DIV_DIVF(divF));
usleep(10);
clkReg[clkCtl] = (BCM_PASSWD | CLK_CTL_MASH(MASH) | CLK_CTL_SRC(clkSrc));
usleep(10);
clkReg[clkCtl] |= (BCM_PASSWD | CLK_CTL_ENAB);
}
void gpioSetMode(unsigned gpio, unsigned mode)
{
int reg, shift;
reg = gpio/10;
shift = (gpio%10) * 3;
gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);
}
int gpioGetMode(unsigned gpio)
{
int reg, shift;
reg = gpio/10;
shift = (gpio%10) * 3;
return (*(gpioReg + reg) >> shift) & 7;
}
/* Values for pull-ups/downs off, pull-down and pull-up. */
#define PI_PUD_OFF 0
#define PI_PUD_DOWN 1
#define PI_PUD_UP 2
void gpioSetPullUpDown(unsigned gpio, unsigned pud)
{
int shift = (gpio & 0xf) << 1;
uint32_t bits;
uint32_t pull;
if (pi_is_2711)
{
switch (pud)
{
case PI_PUD_OFF: pull = 0; break;
case PI_PUD_UP: pull = 1; break;
case PI_PUD_DOWN: pull = 2; break;
}
bits = *(gpioReg + GPPUPPDN0 + (gpio>>4));
bits &= ~(3 << shift);
bits |= (pull << shift);
*(gpioReg + GPPUPPDN0 + (gpio>>4)) = bits;
}
else
{
*(gpioReg + GPPUD) = pud;
usleep(20);
*(gpioReg + GPPUDCLK0 + PI_BANK) = PI_BIT;
usleep(20);
*(gpioReg + GPPUD) = 0;
*(gpioReg + GPPUDCLK0 + PI_BANK) = 0;
}
}
int gpioRead(unsigned gpio)
{
if ((*(gpioReg + GPLEV0 + PI_BANK) & PI_BIT) != 0) return 1;
else return 0;
}
void gpioWrite(unsigned gpio, unsigned level)
{
if (level == 0) *(gpioReg + GPCLR0 + PI_BANK) = PI_BIT;
else *(gpioReg + GPSET0 + PI_BANK) = PI_BIT;
}
void gpioTrigger(unsigned gpio, unsigned pulseLen, unsigned level)
{
if (level == 0) *(gpioReg + GPCLR0 + PI_BANK) = PI_BIT;
else *(gpioReg + GPSET0 + PI_BANK) = PI_BIT;
usleep(pulseLen);
if (level != 0) *(gpioReg + GPCLR0 + PI_BANK) = PI_BIT;
else *(gpioReg + GPSET0 + PI_BANK) = PI_BIT;
}
/* Bit (1<<x) will be set if gpio x is high. */
uint32_t gpioReadBank1(void) { return (*(gpioReg + GPLEV0)); }
uint32_t gpioReadBank2(void) { return (*(gpioReg + GPLEV1)); }
/* To clear gpio x bit or in (1<<x). */
void gpioClearBank1(uint32_t bits) { *(gpioReg + GPCLR0) = bits; }
void gpioClearBank2(uint32_t bits) { *(gpioReg + GPCLR1) = bits; }
/* To set gpio x bit or in (1<<x). */
void gpioSetBank1(uint32_t bits) { *(gpioReg + GPSET0) = bits; }
void gpioSetBank2(uint32_t bits) { *(gpioReg + GPSET1) = bits; }
unsigned gpioHardwareRevision(void)
{
static unsigned rev = 0;
FILE *filp;
char buf[512];
char term;
int chars=4; /* number of chars in revision string */
filp = fopen ("/proc/cpuinfo", "r");
if (filp != NULL)
{
while (fgets(buf, sizeof(buf), filp) != NULL)
{
if (!strncasecmp("revision", buf, 8))
{
if (sscanf(buf+strlen(buf)-(chars+1),
"%x%c", &rev, &term) == 2)
{
if (term != '\n') rev = 0;
else rev &= 0xFFFFFF; /* mask out warranty bit */
}
}
}
fclose(filp);
}
if (filp = fopen("/proc/device-tree/soc/ranges" , "rb"))
{
if (fread(buf, 1, sizeof(buf), filp) >= 8)
{
piPeriphBase = buf[4]<<24 | buf[5]<<16 | buf[6]<<8 | buf[7];
if (!piPeriphBase)
piPeriphBase = buf[8]<<24 | buf[9]<<16 | buf[10]<<8 | buf[11];
if (piPeriphBase == 0xFE000000)
{
pi_is_2711 = 1;
hw_pwm_max_freq = PI_HW_PWM_MAX_FREQ_2711;
clk_plld_freq = CLK_PLLD_FREQ_2711;
}
else
{
hw_pwm_max_freq = PI_HW_PWM_MAX_FREQ;
clk_plld_freq = CLK_PLLD_FREQ;
}
}
fclose(filp);
}
printf("2711 = %d, peri base = %x, rev = %x(%d)\n",
pi_is_2711, piPeriphBase, rev, rev);
return rev;
}
/* Returns the number of microseconds after system boot. Wraps around
after 1 hour 11 minutes 35 seconds.
*/
uint32_t gpioTick(void) { return systReg[SYST_CLO]; }
/* Map in registers. */
static uint32_t * initMapMem(int fd, uint32_t addr, uint32_t len)
{
return (uint32_t *) mmap(0, len,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_LOCKED,
fd, addr);
}
int gpioInitialise(void)
{
int fd;
gpioHardwareRevision(); /* sets rev and peripherals base address */
fd = open("/dev/mem", O_RDWR | O_SYNC) ;
if (fd < 0)
{
fprintf(stderr,
"This program needs root privileges. Try using sudo\n");
return -1;
}
gpioReg = initMapMem(fd, GPIO_BASE, GPIO_LEN);
pwmReg = initMapMem(fd, PWM_BASE, PWM_LEN);
clkReg = initMapMem(fd, CLK_BASE, CLK_LEN);
systReg = initMapMem(fd, SYST_BASE, SYST_LEN);
close(fd);
if ((gpioReg == MAP_FAILED) ||
(systReg == MAP_FAILED) ||
(clkReg == MAP_FAILED) ||
(pwmReg == MAP_FAILED))
{
fprintf(stderr,
"Bad, mmap failed\n");
return -1;
}
return 0;
}
int gpioHardwarePWM(
unsigned gpio, unsigned frequency, unsigned dutycycle)
{
uint32_t old_PWM_CTL;
unsigned pwm, mode;
uint32_t real_range, real_dutycycle;
printf("gpio=%d frequency=%d dutycycle=%d\n",
gpio, frequency, dutycycle);
if (gpio > 31)
printf("bad gpio (%d)\n", gpio);
if (!PWMDef[gpio])
printf("bad gpio for PWM (%d)\n", gpio);
if (dutycycle > 1000000)
printf("bad PWM dutycycle (%d)\n", dutycycle);
if (((frequency < 1) ||
(frequency > hw_pwm_max_freq)) &&
(frequency))
printf(
"bad hardware PWM frequency %d-%d: (%d)\n",
1, hw_pwm_max_freq, frequency);
pwm = (PWMDef[gpio] >> 4) & 3;
mode = PWMDef[gpio] & 7;
if (frequency)
{
real_range = ((double)clk_plld_freq / (2.0 * frequency)) + 0.5;
real_dutycycle = ((uint64_t)dutycycle * real_range) / PI_HW_PWM_RANGE;
/* record the set PWM frequency and dutycycle */
hw_pwm_freq[pwm] =
((double)clk_plld_freq / ( 2.0 * real_range)) + 0.5;
hw_pwm_duty[pwm] = dutycycle;
hw_pwm_real_range[pwm] = real_range;
/* preserve channel enable only and mark space mode */
old_PWM_CTL = pwmReg[PWM_CTL] &
(PWM_CTL_PWEN1 | PWM_CTL_MSEN1 | PWM_CTL_PWEN2 | PWM_CTL_MSEN2);
pwmReg[PWM_CTL] = 0;
usleep(10);
initHWClk(CLK_PWMCTL, CLK_PWMDIV, CLK_CTL_SRC_PLLD, 2, 0, 0);
if (pwm == 0)
{
pwmReg[PWM_RNG1] = real_range;
usleep(10);
pwmReg[PWM_DAT1] = real_dutycycle;
usleep(10);
pwmReg[PWM_CTL] = (old_PWM_CTL | PWM_CTL_PWEN1 | PWM_CTL_MSEN1);
}
else
{
pwmReg[PWM_RNG2] = real_range;
usleep(10);
pwmReg[PWM_DAT2] = real_dutycycle;
usleep(10);
pwmReg[PWM_CTL] = (old_PWM_CTL | PWM_CTL_PWEN2 | PWM_CTL_MSEN2);
}
gpioSetMode(gpio, mode);
printf("range=%d dc=%d\n", real_range, real_dutycycle);
}
else
{
/* frequency 0, stop PWM */
if (pwm == 0) pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN1);
else pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN2);
}
return 0;
}
int main(int argc, char *argv[])
{
int i, freq, gpio, dc;
if (gpioInitialise() < 0) return 1;
if (argc > 1) freq = atoi(argv[1]); else freq = 10;
if (argc > 2) gpio = atoi(argv[2]); else gpio = 12;
if (argc > 3) dc = atoi(argv[3]); else dc = 500000;
gpioHardwarePWM(gpio, freq, dc);
return 0;
} |
If hw is broken then other libs should show the flaw? |
Even the so-called stable frequency values have occasional disturbances - setting my scope to persistent display reveals some ghosting. |
Are these occasional disturbances just on the bcm2711 hardware? wiringPi and bcm2835 have slightly odd hardware PWM implementations. It's not as simple as dialling in a frequency and dutycycle. I might have a look at their implementations. I'm not even sure if they work at all on the later Pis. |
So far I'm only testing on my pi400 - presumably bcm2711C0. More searches dredged up this thread from raspi forums. It is the very same issue. I responded to the OP at the time that I could not reproduce the issue on my Pi400. Now I am able to repro. Was there a firmware update along the way that broke it? |
No idea about firmware changes. I don't see how that would change the functioning of the PWM hardware though, not at the level we are using it. Anyhow I'm done for the day. |
I am testing using the crystal oscillator rather than PLL D as the clock source for hardware PWM. I am going from 1 kHz to 1 MHz in 1 kHz steps. I'm using pigpio with 1 MHz sampling to detect the callbacks on a Pi400. Of course pigpio will fail to keep up way before I reach a frequency of 1 MHz but it seems okay so far. Actually I can only test up to 100 KHz on the Pi400. The bottle neck is Python. piscope sees up to 500 kHz sort of okay. I think I would bite the bullet and give up with PLLD on the BCM2711 (at least for the time being). The oscillator is 54 MHz rather than 750 MHz so we will lose a lot of high frequency PWM. The max PWM frequency would be 13.5 MHz rather than 187.5 MHz but who would try to use that anyhow? |
As far as most people are concerned, 13.5 Mhz would be more than enough ;-) One more observation: If we use hardware pwm via pigpio on a rev 1.4 (
When this happens, the display freezes, and a power cycle is required to get the Pi working again. It looks like the Raspberry Pi firmware is doing something on the rev 1.4 which it is not doing (or differently) on the rev 1.2. |
My plan is to put together an example using another library to do the hardware PWM to compare this with. |
Both the wiringPi and the bcm2835 libraries use the crystal oscillator as the PWM clock source. They should both be okay. |
FWIW:
|
|
While we are on the Pi4B, i wanted to ask if its recommended/not recommended to use pigpio library with RPi.gpio library in a single project? |
I see this issue is still open. One symptom that was mentioned is the erratic behavior of the pwm signal in cases where it was not working correctly, and the fact that an oscilloscope could not sync properly on the signal. That is how "balanced" hardware pwm output appears. The pigpio documentation says that pigpio hardware pwm always uses mark-space. Is it possible that mark-space mode is not always properly initiated, or that something is switching the mode from mark-space to balanced in some cases? |
I'm having trouble finding this. Can you provide a link? TIA |
I can't find mark space mentioned in the docs either (perhaps it was an answer to a question/issue).. It is true though. pigpio only sets mark space mode, Our problem remains that the documentation for the Pi4B etc. shows no material changes to the PWM hardware. |
Sorry, about my statement that the pigpio docs say pigpio hardware pwm always uses mark-space. That statement appears in a comment from joan in the discussion at: https://forums.raspberrypi.com/viewtopic.php?t=244692. As I was switching between the pigpio docs and various web site discussions, I incorrectly remembered that statement as being in the pigpio docs. |
I bought 3 raspiberry pi 4 from amazon last week. All of them have been identified as v1.4. All of them have the same issue as described by this thread. 2 of the pi 4 doesn't have any PWM output from Pin 12. one of the pi 4 has PWM output with pulse width changing over a few pulses on its own when seen using oscilloscope. Just like others reported here, everything works well on pi 3. I have another pi 4, purchased a year before, not v1.4, works just fine; No issue with PWM on pin 12. |
I have a Pi4B Rev 1.4 (b03114), tested several frequencies and all of them are buggy: a duty of 50% prints something 20% ~ 50% randomly. But then I did a simple test: fixed the CPU frequency to maximum (did run some heavy load program at other window, forcing the CPU to maximum) and like magic all frequencies and duty values worked like a charm. So I think it could be something related to the new chipset stepping, maybe the firmware is not prepared correctly. My setup: |
Has anyone experimented with DVFS which is unique to Pi4/Pi400/CM4?
Place |
I added the line to my Pi400 /boot/config.txt. Now commented out as the Pi400 did not boot with the line present.
|
I found @willianwrm 's results interesting: Essentially forcing the system out of dynamic frequency scaling. I was hoping that fixing the voltage scaling would help. |
Hi, i got a similar problem with my RPI4 Rev 1.4 when "sudo insmod pwm.ko", a PWM driver created in c++ and have been tested before on RPI 3. dmesg :-
The Error starts @ ...
|
Apparently we're still without a solution to this problem. Has anyone come up with a work-around? |
Yeah, this one is still unresolved. Make sure you don’t have anything associated with audio running or any other gpio libraries installed. Also, if you are running pigpiod as a service, disable it, reboot and try running from the command line. |
More info If I can summarize what we know:
There has been some talk about audio, etc., but, frankly, I don't see any hard evidence. I admit I'm not an expert here, but it seems to me that there are two reasonable causes:
#1 seems unlikely, given that it shows up only on newer hardware. Is there any way to actually track this down either with the Pi people or with Broadcom? Or are we doomed to live in the dark? |
I have the same problem but on CM4. PWM0 on gpio 12 works fine when using sysfs (/sys/class/pwm/pwmchip0/). But when i try to use gpioHardwarePWM with frequencies 880, 10000, 20000... and dutycycle 50% signal becomes wrong. After testing on diffrents CM4 we have it appears that this happens on CM4 2 GB ram (b03140) BUT gpioHardwarePWM works fine on CM4 4 GB (c03140). I don't know why an amount of ram affects this(there are no other diffrences between CM4(there is only one revision of CM4) as far as i know). |
From https://forums.raspberrypi.com/viewtopic.php?t=329394
Not sure how we can action this. I don't have a Pi4B revision 1.4 board and I guess that will be needed to identify the problem and fix.
The text was updated successfully, but these errors were encountered: