Skip to content
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

Support for the latest Arduino-Pico #619

Closed
stonedev-app opened this issue Sep 26, 2024 · 14 comments
Closed

Support for the latest Arduino-Pico #619

stonedev-app opened this issue Sep 26, 2024 · 14 comments

Comments

@stonedev-app
Copy link

stonedev-app commented Sep 26, 2024

Hello,
I am trying to display text on an SSD1306 using a Raspberry Pi Pico2.

I used the code from the develop branch, but it didn’t work properly.
But, It worked correctly after applying similar modifications to lgfx_gpio_set_function() as in gpio_set_function() in Pico SDK 2.0.0.

The changes have been pushed to the forked stdev branch, and I hope they will be helpful for supporting the latest Arduino-Pico.
https://github.com/stonedev-app/LovyanGFX.git

    bool lgfx_gpio_set_function(int_fast16_t pin, gpio_function_t fn)
    {
      if (pin < 0 || pin >= static_cast<int_fast16_t>(NUM_BANK0_GPIOS))
      {
        return false;
      }
      if ((((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS) != 0)
      {
        return false;
      }
      uint32_t temp = padsbank0_hw->io[pin];
      temp &= ~(PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
      temp |= PADS_BANK0_GPIO0_IE_BITS;
      padsbank0_hw->io[pin] = temp;
      volatile io_bank0_hw_t *iobank0_regs = reinterpret_cast<volatile io_bank0_hw_t *>(IO_BANK0_BASE);
      iobank0_regs->io[pin].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
#if !PICO_RP2040
      // Remove pad isolation now that the correct peripheral is in control of the pad
      hw_clear_bits(&padsbank0_hw->io[pin], PADS_BANK0_GPIO0_ISO_BITS);
#endif
      return true;
    }
@tobozo
Copy link
Collaborator

tobozo commented Sep 26, 2024

hi, thanks for your feedback 👍

are you positive you used the develop branch? this is the exact same code

    bool lgfx_gpio_set_function(int_fast16_t pin, gpio_function_t fn)
    {
      if (pin < 0 || pin >= static_cast<int_fast16_t>(NUM_BANK0_GPIOS))
      {
        return false;
      }
      if ((((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS) != 0)
      {
        return false;
      }
      uint32_t temp = padsbank0_hw->io[pin];
      temp &= ~(PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
      temp |= PADS_BANK0_GPIO0_IE_BITS;
      padsbank0_hw->io[pin] = temp;
      volatile io_bank0_hw_t *iobank0_regs = reinterpret_cast<volatile io_bank0_hw_t *>(IO_BANK0_BASE);
      iobank0_regs->io[pin].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
      return true;
    }

@stonedev-app
Copy link
Author

Tested by adding the following code to the end of lgfx_gpio_set_function() in the develop branch.

#if !PICO_RP2040
      // Remove pad isolation now that the correct peripheral is in control of the pad
      hw_clear_bits(&padsbank0_hw->io[pin], PADS_BANK0_GPIO0_ISO_BITS);
#endif

The fixes in the develop branch resolve the build errors, but the pin configuration doesn't seem to work correctly, and the screen remains black.
By the way, the original Pico should work with the code in the develop branch, but Pico2 did not.

@tobozo
Copy link
Collaborator

tobozo commented Sep 27, 2024

thanks for clarifying, I missed that important detail 🤦

      #if !PICO_RP2040

the recommended usage is to use positive matching:

      #if defined(PICO_RP2350)
        // Remove pad isolation now that the correct peripheral is in control of the pad
        hw_clear_bits(&padsbank0_hw->io[pin], PADS_BANK0_GPIO0_ISO_BITS);
      #endif

but the pin configuration doesn't seem to work correctly, and the screen remains black.

could it be that more functions (e.g. lgfx_gpio_set_pulls()) need RP2350-specific code? 🤔

@stonedev-app
Copy link
Author

I am looking for potential fixes by referencing the differences between Pico SDK 2.0.0 and 1.5.1.
gpio.c in Pico SDK

// Note that, on RP2040, setting both pulls enables a "bus keep" function,
// i.e. weak pull to whatever is current high/low state of GPIO.
void gpio_set_pulls(uint gpio, bool up, bool down) {
    check_gpio_param(gpio);
    hw_write_masked(
            &pads_bank0_hw->io[gpio],
            (bool_to_bit(up) << PADS_BANK0_GPIO0_PUE_LSB) | (bool_to_bit(down) << PADS_BANK0_GPIO0_PDE_LSB),
            PADS_BANK0_GPIO0_PUE_BITS | PADS_BANK0_GPIO0_PDE_BITS
    );
}

Since gpio_set_pulls() does not contain any RP2350-specific code, it seems that lgfx_gpio_set_pulls() does not require RP2350-specific code either.

In gpio.c, it seems that the only function containing RP2350-specific code is gpio_set_function.

At the very least, the following code started working as expected after making modifications to lgfx_gpio_set_function().
Code written using LovyanGFX

@tobozo
Copy link
Collaborator

tobozo commented Sep 28, 2024

if the issue isn't in the gpio layer, then maybe it's in spi layer

adding a DEBUG build flag to the platformio.ini will enable the DBGPRINT macro

[env:rpipico2]
board = rpipico2
build_flags = -DDEBUG

it may be necessary to add more DBGPRINT() statements in common.cpp and Bus_SPI.cpp e.g. to trace the init and compare between rp2040 and rp2350

@stonedev-app
Copy link
Author

Thank you for teaching me how to debug!!
I tried adding debugging settings, but I encountered a build error.
Is an additional debug library required?
I searched for DebugUtil.hpp but couldn't find it.

.pio/libdeps/rpipico2/LovyanGFX/src/lgfx/v1/platforms/rp2040/common.cpp:48:10: fatal error: DebugUtil.hpp: No such file or directory

// #define DEBUG

#if defined(DEBUG)
#include <DebugUtil.hpp>
#else
#define DBGPRINT(fmt, ...)
#define DBG_ENTER()
#define DBGPRINTFUNC(fmt, ...)
#define put_dump_byte(data, addr, length)
#endif

I kind of understand what you're getting at.
You're suggesting that the issue might be caused by differences in the values output during debugging between the RP2040 and RP2350, which is why it doesn't work on the RP2350.

For example, DBGPRINT in lgfx_spi_init().

        // SPI有効化
        spi_regs->cr1 |= SPI_SSPCR1_SSE_BITS;
        DBGPRINT("cr1 %08x\n", spi_regs->cr1);

tobozo added a commit that referenced this issue Oct 3, 2024
@tobozo
Copy link
Collaborator

tobozo commented Oct 4, 2024

I searched for DebugUtil.hpp but couldn't find it.

I believe DebugUtil.hpp contained something like this:

#define DBG_ENTER() printf("\n") 
#define DBGPRINT printf
#define DBGPRINTFUNC(fmt, ...) printf("%s(): " fmt, __func__, ##__VA_ARGS__)

You're suggesting that the issue might be caused by differences in the values

enabling debug will print so much data that differences in the values will be hard to spot, some debug statements will need to be commented out to prevent that.

a more simple test is to check if the init/setup works similarly between rp2040 and rp2350, for this you can simply add some debug messages at specific places

e.g. add DBGPRINTFUNC("returned FALSE") to gpio_init/gpio_set_function:

image

more functions where debug statements can be added:

  • lgfx_gpio_set_dir (look for return false)
  • lgfx_spi_init (look for return false)
  • cpp::result<void, error_t> init (look for return cpp::fail)

@stonedev-app
Copy link
Author

Thank you. I managed to get the debug output working for now.

Inserted DBGPRINTFUNC and tested it on both RP2040 and RP2350.
Since neither output any logs, it seems that there isn't any failure in the implementation.

  • lgfx_gpio_set_function
  • 1gfx_gpio_init
  • lgfx_gpio_set_dir (look for return false)
  • lgfx_spi_init (look for return false)
  • cpp::result<void, error_t> init (look for return cpp::fail)

Thank you for merging the RP2350 fixes into the develop branch.

@tobozo
Copy link
Collaborator

tobozo commented Oct 5, 2024

btw I see that your picoLGFX project has two configs, are you experiencing the same black screen problem with Panel_GC9A01?

other observation: Panel_SSD1306 has cfg.freq_write set to 80MHz, but this page (although not related to raspberrypi) indicates it can't go faster than 10MHz

According to the SSD1306 datasheet, the minimum SPI clock cycle time is 100ns.
Therefore, the maximum SPI clock frequency is 10MHz.

maybe RP2040 somehow automatically corrects the bus speed, but RP2350 doesn't?

it could be interesting to see how RP2040 and RP2350 behave when cfg.freq_write = 8'000'000;

@stonedev-app
Copy link
Author

I checked with a logic analyzer, and it was running at 25MHz.
The capture was done on RP2350, but the same applies to RP2040.
It seems there is no process in place to restrict the frequency to 10MHz or below.

cfg.freq_write = 80000000;

RP2350

It seems to work at about double the frequency, but that feels risky.
Thank you for pointing that out. I'll adjust it to 10MHz.

I will also test the case with Panel_GC9A01.

btw I see that your picoLGFX project has two configs, are you experiencing the same black screen problem with Panel_GC9A01?

@stonedev-app
Copy link
Author

I also tested with the GC9A01, but both the Pico and Pico2 remain with a black screen, and no text is displayed.
Additional code modifications might be necessary.
There is also a slight possibility that I miswired it or that the GC9A01 is damaged.

@tobozo
Copy link
Collaborator

tobozo commented Oct 12, 2024

please see this recent pull request where the pins map was updated for RP2350, it's also very insightful for the pins choice

@stonedev-app
Copy link
Author

Issue resolved, thank you! The cause was a wiring mistake.
I was supplying 5V to the VCC of the GC9A01, but it should have been 3.3V.
I overlooked this because the SSD1306 was working without any problems.

Successfully displayed text on both Pico and Pico2 screens.

@stonedev-app
Copy link
Author

Thank you very much for all the advice!
I believe the issue has been resolved, so I will close this now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants