This is an automated email from Gerrit. bunnie ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4721
-- gerrit commit 9ab8558e5e41b46f5b125e5739566fd587fb35ab Author: bunnie <[email protected]> Date: Tue Oct 16 10:08:51 2018 -0400 work around bcm2835 gpio hardware synchronization bug An issue was found on the Raspberry Pi 3B+ (which may apply to other models) where the BCM2835 GPIO implementation can cause glitches. It looks a bit like this: https://bunniefoo.com/bunnie/openocd-lone-glitch.png https://bunniefoo.com/bunnie/openocd-serial-glitch.png It seems that the GPIO unit on the BCM2835 runs at a much slower clock rate (maybe 125MHz based on the glitch width?) and somehow data committed to/from the CPU is not synched correctly. This would manifest in set/clr events not executing immediately, and also stale data being stuck on the read path. This synch failure could either be due to a cache coherence bug, or it could be a clock domain synchronizer that's not quite working right. My guess is it's the latter -- the synchronizer may be holding off on passing the very last write or read until some arbitrary point later, could be that it misses a bus slot or whatever, but this leads to strictly the correct order of data, but the time at which the data arrives can be highly variable. The glitches would happen maybe once every million cycles or so. The Xilinx XC7 FPGA is fast enough to actually respond to the glitch and continue working if the data levels are constant through the glitched clock, so in many cases the glitch would not lead to an improper configuration. However, we'd see a fault maybe once every few configurations, and SPI programming absolutely would not work with the BCM2835 module (works fine with sysfs). The fix is to insert a dummy read to the BCM2835 GPIO block before doing any read or write transaction. The read seems to flush the synchronizer or cache so that things are in a good state for the next operation. The downside is that the read is slow, this limits the overall bitbang rate, but at least it works as intended. I'm able to clock about a 5MHz rate now, error-free. Change-Id: I5548863f96f9b4702d559fd087bcea7e487b2771 Signed-off-by: bunnie <[email protected]> diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 38ef163..f8f1885 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -91,8 +91,13 @@ static int speed_coeff = 113714; static int speed_offset = 28; static unsigned int jtag_delay; +/* dummy value for synchronizing bcm2835 GPIO transactions */ +static uint32_t lev; + static bb_value_t bcm2835gpio_read(void) { + lev = GPIO_LEV; /* dummy read to synchronize bcm2835 gpio block */ + return (GPIO_LEV & 1<<tdo_gpio) ? BB_HIGH : BB_LOW; } @@ -101,6 +106,7 @@ static int bcm2835gpio_write(int tck, int tms, int tdi) uint32_t set = tck<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio; uint32_t clear = !tck<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio; + lev = GPIO_LEV; /* dummy read to synch bcm2835 gpio block */ GPIO_SET = set; GPIO_CLR = clear; @@ -115,6 +121,7 @@ static int bcm2835gpio_swd_write(int tck, int tms, int tdi) uint32_t set = tck<<swclk_gpio | tdi<<swdio_gpio; uint32_t clear = !tck<<swclk_gpio | !tdi<<swdio_gpio; + lev = GPIO_LEV; GPIO_SET = set; GPIO_CLR = clear; @@ -140,6 +147,7 @@ static int bcm2835gpio_reset(int trst, int srst) clear |= srst<<srst_gpio; } + lev = GPIO_LEV; GPIO_SET = set; GPIO_CLR = clear; @@ -485,6 +493,7 @@ static int bcm2835gpio_init(void) */ INP_GPIO(tdo_gpio); + lev = GPIO_LEV; GPIO_CLR = 1<<tdi_gpio | 1<<tck_gpio | 1<<swdio_gpio | 1<<swclk_gpio; GPIO_SET = 1<<tms_gpio; @@ -495,11 +504,13 @@ static int bcm2835gpio_init(void) OUT_GPIO(swdio_gpio); if (trst_gpio != -1) { trst_gpio_mode = MODE_GPIO(trst_gpio); + lev = GPIO_LEV; GPIO_SET = 1 << trst_gpio; OUT_GPIO(trst_gpio); } if (srst_gpio != -1) { srst_gpio_mode = MODE_GPIO(srst_gpio); + lev = GPIO_LEV; GPIO_SET = 1 << srst_gpio; OUT_GPIO(srst_gpio); } -- _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
