mrcodetastic / ESP32-HUB75-MatrixPanel-DMA

An Adafruit GFX Compatible Library for the ESP32, ESP32-S2, ESP32-S3 to drive HUB75 LED matrix panels using DMA for high refresh rates. Supports panel chaining.
MIT License
899 stars 201 forks source link

NO_GFX/Adafruit_GFX: m_cfg struct seems to be "wrong" when calling "allocateDMAmemory", causing a crash #625

Open robert-budde opened 3 months ago

robert-budde commented 3 months ago

Hi!

I have a very strange problem when using the lib with Adafruit_GFX.

When using the lib with NO_GFX, it does not occur and the lib/panel works as expected.

When compiling without NO_GFX (so with Adafruit_GFX), I get a "division by zero" exception after calling "begin()":

`HUB75_I2S_CFG mxconfig(PANEL_RES_X * 2, PANEL_RES_Y / 2); // for 1/8-scan, double the actual width and half the actual height mxconfig.driver = mxconfig.FM6124; mxconfig.setPixelColorDepthBits(8); dma_display = new MatrixPanel_I2S_DMA(mxconfig);

dma_display->begin();

dma_display->setBrightness8(5); virtualDisp = new VirtualMatrixPanel((*dma_display), 1, 1, PANEL_RES_X, PANEL_RES_Y); virtualDisp->setPhysicalPanelScanRate(FOUR_SCAN_32PX_HIGH);`

I (634) begin(): Using GPIO 4 for R1_PIN I (634) begin(): Using GPIO 5 for G1_PIN I (644) begin(): Using GPIO 6 for B1_PIN I (644) begin(): Using GPIO 7 for R2_PIN I (654) begin(): Using GPIO 15 for G2_PIN I (654) begin(): Using GPIO 16 for B2_PIN I (664) begin(): Using GPIO 18 for A_PIN I (664) begin(): Using GPIO 8 for B_PIN I (664) begin(): Using GPIO 3 for C_PIN I (674) begin(): Using GPIO 42 for D_PIN I (674) begin(): Using GPIO -1 for E_PIN I (684) begin(): Using GPIO 40 for LAT_PIN I (684) begin(): Using GPIO 2 for OE_PIN I (694) begin(): Using GPIO 41 for CLK_PIN I (694) LEDdrivers: MatrixPanel_I2S_DMA - initializing FM6124 driver... I (704) gpio: GPIO[4]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (714) gpio: GPIO[7]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (724) gpio: GPIO[5]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (734) gpio: GPIO[15]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (744) gpio: GPIO[6]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (754) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (764) gpio: GPIO[41]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (764) gpio: GPIO[40]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (774) gpio: GPIO[2]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 E (784) begin(): chain_length: 1 E (794) begin(): clkphase: 1 E (794) begin(): double_buff: 0 E (794) begin(): driver: 1 E (804) begin(): i2sspeed: 15000000 E (804) begin(): latch_blanking: 2 E (814) begin(): min_refresh_rate: 60 E (814) begin(): mx_height: 16 E (814) begin(): mx_width: 128 E (824) begin(): getPixelColorDepthBits: 8 I (824) I2S-DMA: Free heap: 294080 I (834) I2S-DMA: Free SPIRAM: 0 E (834) I2S-DMA: chain_length: 0 E (834) I2S-DMA: clkphase: 0 E (844) I2S-DMA: double_buff: 0 E (844) I2S-DMA: driver: 0 E (854) I2S-DMA: i2sspeed: 1 E (854) I2S-DMA: latch_blanking: 128 E (854) I2S-DMA: min_refresh_rate: 16 E (864) I2S-DMA: mx_height: 0 E (864) I2S-DMA: mx_width: 0 E (864) I2S-DMA: getPixelColorDepthBits: 0 I (874) I2S-DMA: allocating rowBitStructs with pixel_color_depth_bits of 0 E (884) I2S-DMA: m_cfg.mx_height: 0 E (884) I2S-DMA: ROWS_PER_FRAME: 0 I (894) I2S-DMA: Allocating 0 bytes memory for DMA BCM framebuffer(s). I (894) I2S-DMA: Minimum visual refresh rate (scan rate from panel top to bottom) requested: 16 Hz Guru Meditation Error: Core 0 panic'ed (IntegerDivideByZero). Exception was unhandled. Core 0 register dump: PC : 0x4202146e PS : 0x00060330 A0 : 0x82003179 A1 : 0x3fca1e90
A2 : 0x3fcb09d0 A3 : 0x3b9aca00 A4 : 0x00000000 A5 : 0x00000000 A6 : 0x00000000 A7 : 0x00000000 A8 : 0x00000000 A9 : 0x00000000
A10 : 0x00000000 A11 : 0x000000e8 A12 : 0x00000000 A13 : 0x00008000 A14 : 0x3c0604fc A15 : 0x00000010 SAR : 0x00000001 EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x400556d5 LEND : 0x400556e5 LCOUNT : 0xfffffffd
Backtrace: 0x4202146b:0x3fca1e90 0x42003176:0x3fca1ee0 0x4200385b:0x3fca1f00 0x4037f078:0x3fca1fc0 0x40381df9:0x3fca1ff0

I added a lot of Log-Outputs, tracing the HUB75_I2S_CFG information through the calls: It looks like "begin()" itself ist still using the "right" cfg-data, but once "allocateDMAmemory" is called, somehow the wrong HUB75_I2S_CFG struct is accessed. When comparing the function definition of "allocateDMAmemory()" with "configureDMA(const HUB75_I2S_CFG &opts)", "shiftDriver(const HUB75_I2S_CFG &opts)", "fm6124init(const HUB75_I2S_CFG &_cfg)" etc., it strikes me that all other have the dependency injection giving the HUB75_I2S_CFG as an argument. Still, if I hand this over as an argument, it fails as ROWS_PER_FRAME seems to be calculated once upon construction, which still is zero.

Any help would be highly appreciated!

davemaster commented 3 months ago

Greetings,

You build your project from zero in Platform.io, or import from Arduino IDE Project? If you did so, check your board selection, I imagine You build a simple basic example, as the blink and upload to your board, right? Test, if all works fine, re-install (uninstall, then install again) the Adafruit GFX Library. Check also, y if Platform.io is updated y vs code...

robert-budde commented 3 months ago

Thanks for your reply!

Can you please explain how the board selection might affect above setup?

Do you think a working "blink" example will give some more insights - as stated the "NO_GFX" version is already working with the panel as well.

The Adafruit GFX lib is included as a GIT submodule and up-to-date.

robert-budde commented 3 months ago

I don't think it is directly related to the specific Adafruit_GFX lib, it is more related to the was how the MatrixPanel_I2S_DMA is implemented and how the CFG-struct gets thrown around:

Log with "NO_GFX" (working):

E (441) CFG constructor: min_refresh_rate: 60 E (451) CFG constructor: getPixelColorDepthBits: 8 E (451) CFG constructor: CFG-STRUCT ADDRESS: 3fca1f7c E (461) Freelap: min_refresh_rate: 60 E (461) Freelap: getPixelColorDepthBits: 8 E (471) Freelap: CFG-STRUCT ADDRESS: 3fca1f7c E (471) CFG constructor: min_refresh_rate: 60 E (481) CFG constructor: getPixelColorDepthBits: 8 E (481) CFG constructor: CFG-STRUCT ADDRESS: 3fcb0a18 E (491) arg to setCfg: min_refresh_rate: 60 E (491) arg to setCfg: getPixelColorDepthBits: 8 E (501) arg to setCfg: CFG-STRUCT ADDRESS: 3fcb0a18 E (501) m_cfg after setCfg: min_refresh_rate: 60 E (511) m_cfg after setCfg: getPixelColorDepthBits: 8 E (521) m_cfg after setCfg: CFG-STRUCT ADDRESS: 3fcb0a18 E (521) Freelap: min_refresh_rate: 60 E (531) Freelap: getPixelColorDepthBits: 8 E (531) Freelap: CFG-STRUCT ADDRESS: 3fcb0a18 I (541) begin(): Using GPIO 4 for R1_PIN I (541) begin(): Using GPIO 5 for G1_PIN I (551) begin(): Using GPIO 6 for B1_PIN I (551) begin(): Using GPIO 7 for R2_PIN I (551) begin(): Using GPIO 15 for G2_PIN I (561) begin(): Using GPIO 16 for B2_PIN I (561) begin(): Using GPIO 18 for A_PIN I (571) begin(): Using GPIO 8 for B_PIN I (571) begin(): Using GPIO 3 for C_PIN I (581) begin(): Using GPIO -1 for D_PIN I (581) begin(): Using GPIO -1 for E_PIN I (591) begin(): Using GPIO 40 for LAT_PIN I (591) begin(): Using GPIO 2 for OE_PIN I (601) begin(): Using GPIO 41 for CLK_PIN I (601) LEDdrivers: MatrixPanel_I2S_DMA - initializing FM6124 driver... I (611) gpio: GPIO[4]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (621) gpio: GPIO[7]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (631) gpio: GPIO[5]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (641) gpio: GPIO[15]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (641) gpio: GPIO[6]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (651) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (661) gpio: GPIO[41]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (671) gpio: GPIO[40]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (681) gpio: GPIO[2]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 E (691) begin(): min_refresh_rate: 60 E (691) begin(): getPixelColorDepthBits: 8 E (701) begin(): CFG-STRUCT ADDRESS: 3fcb0a18 I (701) I2S-DMA: Free heap: 294112 I (711) I2S-DMA: Free SPIRAM: 0 E (711) allocateDMAmemory: min_refresh_rate: 60 E (721) allocateDMAmemory: getPixelColorDepthBits: 8 E (721) allocateDMAmemory: CFG-STRUCT ADDRESS: 3fcb0a18 I (731) I2S-DMA: allocating rowBitStructs with pixel_color_depth_bits of 8 E (741) allocateDMAmemory: ROWS_PER_FRAME: 8 I (741) I2S-DMA: Allocating 16384 bytes memory for DMA BCM framebuffer(s). I (751) I2S-DMA: Minimum visual refresh rate (scan rate from panel top to bottom) requested: 60 Hz W (761) I2S-DMA: lsbMsbTransitionBit of 0 gives 57 Hz refresh rate. W (771) I2S-DMA: lsbMsbTransitionBit of 1 gives 114 Hz refresh rate. W (771) I2S-DMA: lsbMsbTransitionBit of 1 used to achieve refresh rate of 60 Hz. Percieved colour depth to the eye may be reduced. I (791) I2S-DMA: DMA has pixel_color_depth_bits of 7 I (791) I2S-DMA: Recalculated number of DMA descriptors per row: 64 I (801) I2S-DMA: 512 DMA descriptors linked to buffer data. I (811) S3: Clock divider is 12 I (811) I2S-DMA: DMA setup completed I (4011) main_task: Returned from app_main()

Note once the CFG-struct gets handed over to the constructor of "MatrixPanel_I2S_DMA" its address stays the same (3fcb0a18).

Non-working version (without NO_GFX):

E (443) CFG constructor: min_refresh_rate: 60 E (443) CFG constructor: getPixelColorDepthBits: 8 E (453) CFG constructor: CFG-STRUCT ADDRESS: 3fca1f7c E (453) Freelap: min_refresh_rate: 60 E (463) Freelap: getPixelColorDepthBits: 8 E (463) Freelap: CFG-STRUCT ADDRESS: 3fca1f7c E (473) CFG constructor: min_refresh_rate: 60 E (473) CFG constructor: getPixelColorDepthBits: 8 E (483) CFG constructor: CFG-STRUCT ADDRESS: 3fcb0a38 E (483) arg to setCfg: min_refresh_rate: 60 E (493) arg to setCfg: getPixelColorDepthBits: 8 E (493) arg to setCfg: CFG-STRUCT ADDRESS: 3fcb0a38 E (503) m_cfg after setCfg: min_refresh_rate: 60 E (513) m_cfg after setCfg: getPixelColorDepthBits: 8 E (513) m_cfg after setCfg: CFG-STRUCT ADDRESS: 3fcb0a38 E (523) Freelap: min_refresh_rate: 60 E (523) Freelap: getPixelColorDepthBits: 8 E (533) Freelap: CFG-STRUCT ADDRESS: 3fcb0a38 I (533) begin(): Using GPIO 4 for R1_PIN I (543) begin(): Using GPIO 5 for G1_PIN I (543) begin(): Using GPIO 6 for B1_PIN I (553) begin(): Using GPIO 7 for R2_PIN I (553) begin(): Using GPIO 15 for G2_PIN I (553) begin(): Using GPIO 16 for B2_PIN I (563) begin(): Using GPIO 18 for A_PIN I (563) begin(): Using GPIO 8 for B_PIN I (573) begin(): Using GPIO 3 for C_PIN I (573) begin(): Using GPIO -1 for D_PIN I (583) begin(): Using GPIO -1 for E_PIN I (583) begin(): Using GPIO 40 for LAT_PIN I (593) begin(): Using GPIO 2 for OE_PIN I (593) begin(): Using GPIO 41 for CLK_PIN I (603) LEDdrivers: MatrixPanel_I2S_DMA - initializing FM6124 driver... I (603) gpio: GPIO[4]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (613) gpio: GPIO[7]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (623) gpio: GPIO[5]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (633) gpio: GPIO[15]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (643) gpio: GPIO[6]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (653) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (663) gpio: GPIO[41]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (673) gpio: GPIO[40]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (683) gpio: GPIO[2]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 E (693) begin(): min_refresh_rate: 60 E (693) begin(): getPixelColorDepthBits: 8 E (703) begin(): CFG-STRUCT ADDRESS: 3fcb0a38 I (703) I2S-DMA: Free heap: 294080 I (703) I2S-DMA: Free SPIRAM: 0 E (713) allocateDMAmemory: min_refresh_rate: 16 E (713) allocateDMAmemory: getPixelColorDepthBits: 0 E (723) allocateDMAmemory: CFG-STRUCT ADDRESS: 3fcb0a18 I (733) I2S-DMA: allocating rowBitStructs with pixel_color_depth_bits of 0 E (733) allocateDMAmemory: ROWS_PER_FRAME: 0 I (743) I2S-DMA: Allocating 0 bytes memory for DMA BCM framebuffer(s). I (753) I2S-DMA: Minimum visual refresh rate (scan rate from panel top to bottom) requested: 16 Hz Guru Meditation Error: Core 0 panic'ed (IntegerDivideByZero). Exception was unhandled. Core 0 register dump: PC : 0x42020fa2 PS : 0x00060330 A0 : 0x82002f69 A1 : 0x3fca1ea0 A2 : 0x3fcb09d0 A3 : 0x3b9aca00 A4 : 0x00000000 A5 : 0x3fcb0a40
A6 : 0x00000000 A7 : 0x00000000 A8 : 0x00000000 A9 : 0x00000000 A10 : 0x00000000 A11 : 0x000000e8 A12 : 0x00000000 A13 : 0x00008000

Please observe the address of the CFG-struct: everything is fine until "allocateDMAmemory" grabs it from the "wrong" address (in this case 3fcb0a18 (but 3fcb0a38 would be correct).

I somehow think "allocateDMAmemory" does not know the correct offset as the inheritance from the "Adafruit_GFX" class offsets some variables of the derived class...