• Re: Baremetal programiing the Pimoroni Tiny2040 RGB LED

    From The Natural Philosopher@3:633/10 to All on Sun Jan 11 19:36:45 2026
    On 11/01/2026 16:15, Single Stage to Orbit wrote:
    Hi chaps

    Does this group also include the Raspberry rp2040/rp2350 as well? I'm
    in need of resources or the knowledge of how to program the PWMs on the rp2040. If not, are there any online resource I can consult.

    I certainly have been playing with these in a C context.

    I klooked into PWM in some detail but have not yet implemented it.

    The rp2040 datasheets are instrutable on the subject of the PWMs. I can easily blink an ordinary LED, likewise for a RGB LED via three GPIO
    pins, but for doing cool tricks like fading/brightening the separate
    RGB components on a RGB LED it's beyond me, I think PWMs are needed for
    this but all I could find was micropython stuff and that works but I'd
    like to know how to do it baremetal with ARM thumb assembly.

    Cant help with assembly, only C.

    IIRC there are a couple of places you just wrote data to to set the
    thing up and these can be rewritten live to vary the pulse width

    Easy way to do that is to run a sleep_ms(loop) and every iterations
    change something for a fade up down.

    From: https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_pwm


    The RP2040 PWM block has 8 identical slices, the RP2350 has 12. Each
    slice can drive two PWM output signals, or measure the frequency or duty
    cycle of an input signal. This gives a total of up to 16/24 controllable
    PWM outputs. All 30 GPIOs can be driven by the PWM block.

    The PWM hardware functions by continuously comparing the input value to
    a free-running counter. This produces a toggling output where the amount
    of time spent at the high output level is proportional to the input
    value. The fraction of time spent at the high signal level is known as
    the duty cycle of the signal.

    The default behaviour of a PWM slice is to count upward until the wrap
    value (pwm_config_set_wrap) is reached, and then immediately wrap to 0.
    PWM slices also offer a phase-correct mode, where the counter starts to
    count downward after reaching TOP, until it reaches 0 again.

    // Output PWM signals on pins 0 and 1

    #include "pico/stdlib.h"
    #include "hardware/pwm.h"

    int main() {

    // Tell GPIO 0 and 1 they are allocated to the PWM
    gpio_set_function(0, GPIO_FUNC_PWM);
    gpio_set_function(1, GPIO_FUNC_PWM);

    // Find out which PWM slice is connected to GPIO 0 (it's slice 0)
    uint slice_num = pwm_gpio_to_slice_num(0);

    // Set period of 4 cycles (0 to 3 inclusive)
    pwm_set_wrap(slice_num, 3);
    // Set channel A output high for one cycle before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_A, 1);
    // Set initial B output high for three cycles before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_B, 3);
    // Set the PWM running
    pwm_set_enabled(slice_num, true);

    // Note we could also use pwm_set_gpio_level(gpio, x) which looks
    up the
    // correct slice and channel for a given GPIO.
    }

    Now that references a c library, but easy enough to pull assembler
    source out of it


    Many thanks,
    Alex

    --
    ?It is dangerous to be right in matters on which the established
    authorities are wrong.?

    ? Voltaire, The Age of Louis XIV


    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Daniel James@3:633/10 to All on Sun Jan 11 18:52:17 2026
    On 11/01/2026 16:15, Single Stage to Orbit wrote:
    Does this group also include the Raspberry rp2040/rp2350 as well?

    I don't see why not ...

    The rp2040 datasheets are instrutable on the subject of the PWMs.

    Agreed. The official documentation for everything but Python is sketchy
    at best. Superficially it looks great, but on closer inspection it is
    found to present all the right words without imbuing them with any meaning.

    However: There is a section on hardware PWM in the Pico-series C/C++
    SDK, have you seen that?

    I confess it's not something I've played with, but it doesn't look too impenetrable ... it doesn't require PIO programming (something else I
    haven't played with yet) like another example I found.

    I'm not sure how long ago I downloaded this SDK so it may not be quite
    current ... but it's section 4.1.18 on P249.

    If you used a capable search engine you might stumble across this:

    https://forums.raspberrypi.com/viewtopic.php?t=344634

    which seems to shed some light ...

    --
    Cheers,
    Daniel.

    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Single Stage to Orbit@3:633/10 to All on Sun Jan 11 16:15:59 2026
    Hi chaps

    Does this group also include the Raspberry rp2040/rp2350 as well? I'm
    in need of resources or the knowledge of how to program the PWMs on the
    rp2040. If not, are there any online resource I can consult.

    The rp2040 datasheets are instrutable on the subject of the PWMs. I can
    easily blink an ordinary LED, likewise for a RGB LED via three GPIO
    pins, but for doing cool tricks like fading/brightening the separate
    RGB components on a RGB LED it's beyond me, I think PWMs are needed for
    this but all I could find was micropython stuff and that works but I'd
    like to know how to do it baremetal with ARM thumb assembly.

    Many thanks,
    Alex
    --
    Tactical Nuclear Kittens


    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Gordon Henderson@3:633/10 to All on Tue Jan 13 09:30:01 2026
    In article <d03091c18c489926db7aef8286bf865162298441.camel@munted.eu>,
    Single Stage to Orbit <alex.buell@munted.eu> wrote:
    Hi chaps

    Does this group also include the Raspberry rp2040/rp2350 as well?

    I'd like to think so, but it's somewhat niche (Baremetal that is)
    however...

    like to know how to do it baremetal with ARM thumb assembly.

    ... my use is the RISC-V cores in the rp2350, so bare metal RISC-V
    asembly.... But the principle for programming the PWM generators
    is more or less the same from eith CPU, so I understand, but it's
    something I've not gotten round to.

    I'd suggest to have a look at the manual and SDK and see how to do it
    from C then hand translate the C code into ASM...

    Gordon

    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Single Stage to Orbit@3:633/10 to All on Sat Jan 17 15:21:51 2026
    On Mon, 2026-01-12 at 10:57 +0000, Gordon Henderson wrote:
    like to know how to do it baremetal with ARM thumb assembly.

    ... my use is the RISC-V cores in the rp2350, so bare metal RISC-V asembly.... But the principle for programming the PWM generators
    is more or less the same from eith CPU, so I understand, but it's
    something I've not gotten round to.

    I'd suggest to have a look at the manual and SDK and see how to do it
    from C then hand translate the C code into ASM...

    I've found the following:

    https://github.com/thejpster/rp-hal-rp2350-public/blob/main/rp235x-hal/exam ples/pwm_blink.rs

    Looks like this is what I've been looking for.

    The funny thing is that the Pimoroni tiny2040 that I also have has a
    RGB LED on it, there's no data sheet for it but it appears to be
    reversed, in that all the GPIO pins attached to this LED are all active
    low, (i.e ~R GPIO18, ~B GPIO19, ~G GPIO20) so works in the opposite way
    to the LED on GPIO 25 on rp2040!
    --
    Tactical Nuclear Kittens


    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Single Stage to Orbit@3:633/10 to All on Sat Jan 17 15:07:21 2026
    On Sun, 2026-01-11 at 19:36 +0000, The Natural Philosopher wrote:
    From: https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_ha
    rdware_pwm

    Excellent, I missed that one.

    Thanks,
    Alex
    --
    Tactical Nuclear Kittens


    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Single Stage to Orbit@3:633/10 to All on Sat Jan 17 15:04:30 2026
    On Sun, 2026-01-11 at 18:52 +0000, Daniel James wrote:


    However: There is a section on hardware PWM in the Pico-series C/C++
    SDK, have you seen that?

    Oh interesting, I can take a look at that. Hopefully the sources will
    clarify what's required.

    I confess it's not something I've played with, but it doesn't look
    too impenetrable ... it doesn't require PIO programming (something
    else I haven't played with yet) like another example I found.

    No, you're right, thankfully I don't need to go down that PIO rabbit
    hole yet. Just to demysterify how to do the PWM in assembly.

    I'm not sure how long ago I downloaded this SDK so it may not be
    quite current ... but it's section 4.1.18 on P249.

    If you used a capable search engine you might stumble across this:

    https://forums.raspberrypi.com/viewtopic.php?t=344634

    which seems to shed some light ...

    Thanks.
    --
    Tactical Nuclear Kittens


    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael Schwingen@3:633/10 to All on Sun Jan 18 10:32:40 2026
    On 2026-01-17, Single Stage to Orbit <alex.buell@munted.eu> wrote:
    I'd suggest to have a look at the manual and SDK and see how to do it
    from C then hand translate the C code into ASM...

    I've found the following:

    https://github.com/thejpster/rp-hal-rp2350-public/blob/main/rp235x-hal/examples/pwm_blink.rs

    Why not go to the primary source?

    I believe the RP2xx0 datasheet has all you need in the PWM chapter (CH 4.5
    for RP2040, or CH 12.5 for RP2350).

    There is a list of registers with all the relevant bits explained.

    The funny thing is that the Pimoroni tiny2040 that I also have has a
    RGB LED on it, there's no data sheet for it but it appears to be
    reversed, in that all the GPIO pins attached to this LED are all active
    low, (i.e ~R GPIO18, ~B GPIO19, ~G GPIO20) so works in the opposite way
    to the LED on GPIO 25 on rp2040!

    This is quite common - they probably used a 4-pin LED package with common anode, so you have to drive the individual lines low to activate the LED.
    You could use 3 external inverters or transistors to make them active high,
    but why bother (the parts cost money and take up PCB space) when all it
    takes to fix this is a single line of code on the software side?

    cu
    Michael
    --
    Some people have no respect of age unless it is bottled.

    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Daniel James@3:633/10 to All on Sun Jan 18 12:37:31 2026
    On 17/01/2026 15:21, Single Stage to Orbit wrote:
    The funny thing is that the Pimoroni tiny2040 that I also have has a
    RGB LED on it, there's no data sheet for it but it appears to be
    reversed, in that all the GPIO pins attached to this LED are all active
    low, (i.e ~R GPIO18, ~B GPIO19, ~G GPIO20) so works in the opposite way
    to the LED on GPIO 25 on rp2040!

    Did you read Pimoroni's own website entry for that part?

    https://shop.pimoroni.com/products/tiny-2040

    where it says:

    *Notes*

    * The RGB LED is connected to GP18-GP20 and active low (so the
    on/off state will work in the opposite way to the LED on a
    Raspberry Pi Pico). You can PWM the pins to dim the LED - check
    out Tonygo2's MicroPython example.

    The example cited is Python, so not directly of use to you, but here is
    the link, anyway:

    https://forums.pimoroni.com/t/tiny-2040-rgb-led-control-tutorial/16604


    --
    Cheers,
    Daniel.

    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)