ESP-IDF v5.4: array-bounds errors in common.cpp
S:/Espressif/frameworks/esp-idf-v5.4.1/components/hal/esp32c6/include/hal/gpio_ll.h: In function 'void gpio_ll_matrix_out_default(gpio_dev_t*, uint32_t)':
S:/Espressif/frameworks/esp-idf-v5.4.1/components/hal/esp32c6/include/hal/gpio_ll.h:320:5: warning: missing initializer for member 'gpio_func_out_sel_cfg_reg_t::<unnamed struct>::out_inv_sel' [-Wmissing-field-initializers]
320 | };
| ^
S:/Espressif/frameworks/esp-idf-v5.4.1/components/hal/esp32c6/include/hal/gpio_ll.h:320:5: warning: missing initializer for member 'gpio_func_out_sel_cfg_reg_t::<unnamed struct>::oen_sel' [-Wmissing-field-initializers]
S:/Espressif/frameworks/esp-idf-v5.4.1/components/hal/esp32c6/include/hal/gpio_ll.h:320:5: warning: missing initializer for member 'gpio_func_out_sel_cfg_reg_t::<unnamed struct>::oen_inv_sel' [-Wmissing-field-initializers]
S:/Espressif/frameworks/esp-idf-v5.4.1/components/hal/esp32c6/include/hal/gpio_ll.h:320:5: warning: missing initializer for member 'gpio_func_out_sel_cfg_reg_t::<unnamed struct>::reserved_11' [-Wmissing-field-initializers]
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp: In function 'cpp::bitwizeshift::result<void, lgfx::v1::error_t> lgfx::v1::spi::init(int, int, int, int, int)':
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp:608:7: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
608 | *reg(SPI_USER_REG(spi_port)) = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN; // need SD card access (full duplex setting)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus.exe: note: source object is likely at address zero
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp: In function 'void lgfx::v1::spi::beginTransaction(int, uint32_t, int)':
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp:693:7: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
693 | *reg(SPI_USER_REG(spi_port)) = user;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus.exe: note: source object is likely at address zero
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp:697:7: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
697 | *reg(SPI_MISC_REG( spi_port)) = pin;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus.exe: note: source object is likely at address zero
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp:699:7: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
699 | *reg(SPI_CLOCK_REG(spi_port)) = clkdiv;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus.exe: note: source object is likely at address zero
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp: In function 'void lgfx::v1::spi::writeBytes(int, const uint8_t*, size_t)':
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp:729:7: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
729 | *reg(SPI_MOSI_DLEN_REG(spi_port)) = (len << 3) - 1;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus.exe: note: source object is likely at address zero
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp: In function 'void lgfx::v1::spi::readBytes(int, uint8_t*, size_t)':
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.cpp:740:7: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
740 | *reg(SPI_MOSI_DLEN_REG(spi_port)) = (len << 3) - 1;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus.exe: note: source object is likely at address zero
SoC ?
SoC ?
seems to be mainly c5 and c6
Hello, @jaylikesbunda I just update release v0.2.9.
Perhaps this issue has been solved.
unfortunately not, this is trying with the c5
In file included from S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/common.hpp:22,
from S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/lgfx_fonts.cpp:3:
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp: In function 'volatile uint32_t* lgfx::v1::get_gpio_hi_reg(int_fast8_t)':
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp:144:89: error: conditional expression between distinct pointer types 'volatile uint32_t*' {aka 'volatile long unsigned int*'} and 'volatile gpio_out_w1ts_reg_t*' lacks a cast
144 | static inline volatile uint32_t* get_gpio_hi_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1ts.val : &GPIO.out_w1ts; }
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp:144:89: error: invalid conversion from 'volatile void*' to 'volatile uint32_t*' {aka 'volatile long unsigned int*'} [-fpermissive]
144 | static inline volatile uint32_t* get_gpio_hi_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1ts.val : &GPIO.out_w1ts; }
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| volatile void*
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp: In function 'volatile uint32_t* lgfx::v1::get_gpio_lo_reg(int_fast8_t)':
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp:146:89: error: conditional expression between distinct pointer types 'volatile uint32_t*' {aka 'volatile long unsigned int*'} and 'volatile gpio_out_w1tc_reg_t*' lacks a cast
146 | static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1tc.val : &GPIO.out_w1tc; }
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp:146:89: error: invalid conversion from 'volatile void*' to 'volatile uint32_t*' {aka 'volatile long unsigned int*'} [-fpermissive]
146 | static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1tc.val : &GPIO.out_w1tc; }
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| volatile void*
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp: In function 'bool lgfx::v1::gpio_in(int_fast8_t)':
S:/GhostESP2/Ghost_ESP/components/M5GFX/src/lgfx/v1/platforms/esp32/common.hpp:148:79: error: 'volatile union gpio_in1_reg_t' has no member named 'data'
148 | static inline bool gpio_in(int_fast8_t pin) { return ((pin & 32) ? GPIO.in1.data : GPIO.in) & (1 << (pin & 31)); }
|
I don't understand M5Stack products that use ESP32C5. What is the hardware configuration?
Issue Title
Compilation error due to out-of-bounds array access in Bus_SPI.cpp with ESP-IDF v5.4.1 on M5Tab5 (ESP32P4)
Description
When compiling M5GFX with ESP-IDF v5.4.1 for the M5Tab5 device (which uses ESP32P4), I encountered the following compilation errors:
X/Tab5P4Demo/components/M5GFX/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp: In member function 'virtual void lgfx::v1::Bus_SPI::endRead()':
X/Tab5P4Demo/components/M5GFX/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp:884:5: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
884 | *reg(SPI_PIN_REG(_spi_port)) = pin;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: source object is likely at address zero
X/Tab5P4Demo/components/M5GFX/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp: In member function 'virtual void lgfx::v1::Bus_SPI::beginRead()':
X/Tab5P4Demo/components/M5GFX/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp:873:5: error: array subscript 0 is outside array bounds of 'volatile uint32_t [0]' [-Werror=array-bounds=]
873 | *reg(SPI_PIN_REG(_spi_port)) = pin;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: source object is likely at address zero
cc1plus: some warnings being treated as errors
This is caused by the macro SPI_PIN_REG(_spi_port) returning an invalid address or an empty array for _spi_port values < 2, resulting in illegal array subscripting that GCC catches as an error (-Werror=array-bounds). By the way, I use the file "sdkconfig" in Tab5UserDemo.
Cause
The issue arises because the base register definition and reg() macro in Bus_SPI.cpp only expect SPI ports >= 2. leading to illegal accesses.
Workaround / Fix
I modified the beginRead() and endRead() functions to check if _spi_port is 2 or greater, and only then access the SPI_PIN_REG and SPI_CLOCK_REG registers:
/*REG_SPI_BASE in soc.h ⬇️*/
#define REG_SPI_BASE(i) (((i)>=2) ? (DR_REG_SPI2_BASE + (i-2) * 0x1000) : (0)) // GPSPI2 and GPSPI3
// ============
/*Bus_SPI.cpp*/
void Bus_SPI::beginRead(void)
{
uint32_t pin = (_cfg.spi_mode & 2) ? SPI_CK_IDLE_EDGE : 0;
uint32_t user = ((_cfg.spi_mode == 1 || _cfg.spi_mode == 2) ? SPI_CK_OUT_EDGE | SPI_USR_MISO : SPI_USR_MISO)
| (_cfg.spi_3wire ? SPI_SIO : 0);
dc_control(true);
*_spi_user_reg = user;
// Add condition to prevent invalid register access for spi_port >= 2
if (_spi_port >= 2) {
*reg(SPI_PIN_REG(_spi_port)) = pin;
*reg(SPI_CLOCK_REG(_spi_port)) = _clkdiv_read;
}
#if defined ( SPI_UPDATE )
*_spi_cmd_reg = SPI_UPDATE;
#endif
}
void Bus_SPI::endRead(void)
{
uint32_t pin = (_cfg.spi_mode & 2) ? SPI_CK_IDLE_EDGE : 0;
*_spi_user_reg = _user_reg;
if (_spi_port >= 2) {
*reg(SPI_PIN_REG(_spi_port)) = pin;
*reg(SPI_CLOCK_REG(_spi_port)) = _clkdiv_write;
}
#if defined ( SPI_UPDATE )
*_spi_cmd_reg = SPI_UPDATE;
#endif
}
With this change, the illegal memory access is avoided and the code compiles successfully.
Request
Could the maintainers consider adding this conditional check or a more robust way to handle SPI ports on ESP32P4 to the official M5GFX codebase? This will improve compatibility with ESP-IDF v5.4.1 and ESP32P4 hardware.
@lovyan03 Please let me know if you need any further details or testing results from my side. Thank you very much for your attention and support.
@nanshenwei Thank you for the detailed information ! A mechanism to avoid the problem has been implemented in the develop branch, so please try it out. Although I think the idea of avoiding a setting value of less than 2 by using an if statement condition is great, careful consideration is needed as it is unclear whether 2 will be sufficient for future ESP32 series.