drivers/lcd: fix apa102/max7219 object name collision with drivers/leds - #19785
drivers/lcd: fix apa102/max7219 object name collision with drivers/leds#19785ricardgb wants to merge 2 commits into
Conversation
drivers/ is built by a single flat Makefile: every per-directory Make.defs appends its sources to one CSRCS list and its directory to one VPATH, and the objects all land in drivers/ named after the source basename. Two sources with the same basename in different subdirectories therefore map to the same object, and make resolves the prerequisite through VPATH, which is searched in the order drivers/Makefile includes the Make.defs files. lcd is included before leds, so drivers/lcd always wins. Both apa102 and max7219 exist twice, once as an LCD front-end and once as an LED driver: drivers/lcd/apa102.c CONFIG_LCD_APA102 drivers/leds/apa102.c CONFIG_LEDS_APA102 drivers/lcd/max7219.c CONFIG_LCD_MAX7219 drivers/leds/max7219.c CONFIG_LEDS_MAX7219 drivers/lcd/Make.defs puts lcd on the VPATH for the whole directory whenever CONFIG_LCD=y, so selecting only the LED driver still builds apa102.o from drivers/lcd/apa102.c and the selected LED driver is never compiled at all. Because the LCD front-ends take their constants from include/nuttx/lcd/apa102.h and include/nuttx/lcd/max7219.h, which are behind CONFIG_LCD_APA102 / CONFIG_LCD_MAX7219, the substituted source does not even compile. With CONFIG_LCD=y + CONFIG_LEDS_APA102=y and CONFIG_LCD_APA102 unset: lcd/apa102.c:701:20: error: 'APA102_BLACK' undeclared (first use in this function); did you mean 'APA102_BPP'? and correspondingly for CONFIG_LEDS_MAX7219 without CONFIG_LCD_MAX7219: lcd/max7219.c:773:20: error: 'MAX7219_BLACK' undeclared (first use in this function); did you mean 'MAX7219_BPP'? So neither LED driver can be built together with CONFIG_LCD, and there is no diagnostic pointing at the real cause. Give the LCD front-ends distinct basenames. The LCD side is the adapted use of these parts (an LED matrix driven as a display), and drivers/lcd already names such variants for their role, e.g. ht16k33_14seg.c, so the suffix goes there and the LED drivers keep the plain part names. The CMake build derives object paths from the source directory and was never affected; its source lists are updated to match. Signed-off-by: Ricard Rosson <ricard@groundbits.com> Assisted-by: Claude Opus 5 (Claude Code)
drivers/lcd/Kconfig offers CONFIG_LCD_APA102_XRES, CONFIG_LCD_APA102_YRES and CONFIG_LCD_APA102_FREQUENCY under "if LCD_APA102", but apa102_lcd.c tests for CONFIG_APA102_XRES, CONFIG_APA102_YRES and CONFIG_APA102_FREQUENCY, which no Kconfig file defines. The #ifndef fallbacks therefore always win and the matrix geometry is hard-wired to 16x16 no matter what is configured. The frequency setting is doubly dead: even the fallback is unused, because apa102_configspi() calls SPI_SETFREQUENCY() with APA102_SPI_MAXFREQUENCY from include/nuttx/leds/apa102.h, which is 100 kHz (its "Default 4MHz" comment notwithstanding), so the chain is always clocked at 100 kHz. Use the names the Kconfig actually defines and drive the bus at the configured frequency. The fallback definitions are kept for an out-of-Kconfig build and given the Kconfig defaults; 16x16 keeps the previous geometry for anyone who never set the options. Verified on stm32f4discovery:nsh with CONFIG_LCD_APA102_XRES=8, CONFIG_LCD_APA102_YRES=4 and CONFIG_LCD_APA102_FREQUENCY=4000000: the shadow framebuffer in g_apa102dev shrinks to 8x4 LEDs and the SPI frequency argument is 0x003d0900, where before the settings had no effect at all. Signed-off-by: Ricard Rosson <ricard@groundbits.com> Assisted-by: Claude Opus 5 (Claude Code)
I have a stm32f4discovery laying around. I'll give it a try |
The board I have is different, so I can't test it. However the compilation doesn't throw any errors: stm32f4discovery:nsh (default): builds clean — no regression. stm32f4discovery with CONFIG_LCD + CONFIG_LEDS_APA102 + CONFIG_LEDS_MAX7219 (the exact combo that fails on master with the APA102_BLACK/MAX7219_BLACK collision): builds clean — the fix resolves it. With LCD=y but LCD_APA102 unset, only drivers/leds/apa102.o compiles (the lcd side is now apa102_lcd.c, gated on its own option), so no shadowing. |
Summary
Two build-level defects around the APA102 RGB-LED driver, found while bringing an APA102 strip up on an ESP32-S3 board.
1.
drivers/lcd/apa102.canddrivers/leds/apa102.ccollide on one object namedrivers/is built by a single flatMakefile. Each per-directoryMake.defsappends to one sharedCSRCSlist and one sharedVPATH, and every object lands indrivers/named after the basename of its source. Two sources with the same basename in different subdirectories therefore map to the same object file, and make resolves the prerequisite throughVPATH, which is searched in the orderdrivers/Makefileincludes theMake.defsfiles.lcdis included beforeleds, sodrivers/lcdalways wins.Two part names exist in both directories:
drivers/lcd/apa102.cCONFIG_LCD_APA102drivers/leds/apa102.cCONFIG_LEDS_APA102drivers/lcd/max7219.cCONFIG_LCD_MAX7219drivers/leds/max7219.cCONFIG_LEDS_MAX7219drivers/lcd/Make.defsaddslcdto theVPATHfor the whole directory wheneverCONFIG_LCD=y, so selecting only the LED driver still compiles the LCD source intoapa102.o/max7219.oand the selected LED driver is never compiled at all. Because the LCD front-ends take their constants frominclude/nuttx/lcd/apa102.h/include/nuttx/lcd/max7219.h, which are guarded byCONFIG_LCD_APA102/CONFIG_LCD_MAX7219, the substituted source does not even compile. WithCONFIG_LCD=y+CONFIG_LEDS_APA102=yandCONFIG_LCD_APA102unset:and the same for
CONFIG_LEDS_MAX7219withoutCONFIG_LCD_MAX7219('MAX7219_BLACK' undeclared, plusMAX7219_POWER_OFF,MAX7219_SHUTDOWN, …). Net effect: neither LED driver can be built in any configuration that also enablesCONFIG_LCD, and the error message points at a file the user never selected.Fix: give the LCD front-ends distinct basenames (
apa102_lcd.c,max7219_lcd.c, viagit mvso history follows). The LCD side is the adapted use of these parts — an LED matrix driven as a display — anddrivers/lcdalready names such variants for their role (e.g.ht16k33_14seg.c), so the suffix goes there and the LED drivers keep the plain part names.drivers/lcd/Make.defsanddrivers/lcd/CMakeLists.txtare both updated, plus the two.github/CODEOWNERSlines.The CMake build was never affected:
target_sources()resolves relative paths against the current source directory and CMake namespaces object paths per directory, so bothapa102.cfiles can coexist there. Only the Make build is broken. The CMake source lists are updated purely to match the new filenames.Other duplicate basenames in
drivers/— the only remaining one isskeleton.c, which exists four times (ioexpander/,lcd/,mtd/,net/). Three of those are unbuilt driver templates; onlydrivers/net/skeleton.cis ever added toCSRCS(CONFIG_NET_SKELETON), and becauselcdprecedesnetin the include order it would be shadowed bydrivers/lcd/skeleton.cin anyCONFIG_LCD=ybuild. That is the same latent defect, but it only affects a template driver, so it is left out of this PR to keep the change focused — happy to rename those too if maintainers prefer.2. The APA102 LCD driver ignores its own Kconfig settings
drivers/lcd/KconfigoffersCONFIG_LCD_APA102_XRES,CONFIG_LCD_APA102_YRESandCONFIG_LCD_APA102_FREQUENCYunderif LCD_APA102, but the driver testsCONFIG_APA102_XRES,CONFIG_APA102_YRESandCONFIG_APA102_FREQUENCY— names no Kconfig file in the tree defines. The#ifndeffallbacks therefore always win and the geometry is hard-wired to 16x16 regardless of configuration. The frequency setting is doubly dead: even the fallback is unused, becauseapa102_configspi()passesAPA102_SPI_MAXFREQUENCYfrominclude/nuttx/leds/apa102.h, which is 100 kHz (its/* Default 4MHz */comment notwithstanding), so the chain is always clocked at 100 kHz.Fix: use the names Kconfig actually defines, and drive the bus at the configured frequency. The
#ifndeffallbacks are kept for an out-of-Kconfig build and aligned with the Kconfig defaults; 16x16 preserves the previous geometry for anyone who never set the options.Impact
CONFIG_LCD=ytogether withCONFIG_LEDS_APA102=yorCONFIG_LEDS_MAX7219=ybuild for the first time, and build the driver that was actually selected.CONFIG_LCD_APA102/CONFIG_LCD_MAX7219configurations are unchanged apart from the source filename — same code, same symbols (apa102_initialize,max7219_initialize).drivers/lcdreferences these.cfiles by name (board glue links against the headers).CONFIG_LCD_APA102_*settings start taking effect. For a configuration that never set them the behaviour is identical except for the SPI clock, which moves from the hard-coded 100 kHz to the Kconfig default of 1 MHz.Testing
Build-verified on
stm32f4discovery:nsh(arm-none-eabi-gcc, no new warnings).drivers/Make.depis quoted because it records which source each object was actually built from:tools/checkpatch.sh -gon the two commits: all checks pass.The
drivers/leds/apa102.cLED-strip path itself was exercised on hardware today (APA102 on an ESP32-S3 SPI bus,apps/examples/apa102writing a colour cycle to/dev/leddrv0) — that is what surfaced the collision. The change in this PR is build-verified only; the APA102/MAX7219 LCD front-ends are pure renames plus the Kconfig-name fix and were not exercised on a panel.Disclosure
This analysis, patch, and build validation were performed by an AI agent (Claude Code, operated and directed by the submitter), and the result was reviewed by the submitter before posting.