raspberrypi / pico-sdk

BSD 3-Clause "New" or "Revised" License
3.24k stars 837 forks source link

Writing 0 to SIO's GPIO_OUT register does not turn outputs off #1742

Closed soypat closed 1 week ago

soypat commented 1 week ago

I've written the following program in Go that blinks the LED via raw writes to registers. Setting the GPIO_OUT of the LED (pin 25) on the pico turns the LED on, but when we write 0 to the register to clear all the bits it does not turn off.

Writing to GPIO_OUT_CLR does turn the LED off, and this is in effect what pico-sdk does to turn LEDs off. Is this an issue with the silicon?

package main

import (
    "time"
    "unsafe"
)

func main() {
    const ledPin = 25
    const addrIObank = 0x40014000
    const addrSIO = 0xd0000000
    const offGPIO = 0x14
    const offEnable = 0x20
    const offGPIOclr = 0x18
    const sizeIOPinBlk = 4 * 2
    const offIOPinCtrl = 4
    const fnIOGPIO = 5
    // Enable GPIO function in the pin Control IO bank.
    writeRegister(addrIObank+ledPin*sizeIOPinBlk+offIOPinCtrl, fnIOGPIO)
    // Enable digital output on that pin in the SIO.
    writeRegister(addrSIO+offEnable, 1<<ledPin)
    // Set Output ON.
    for {
        writeRegister(addrSIO+offGPIO, 1<<ledPin)
        time.Sleep(time.Second)
        writeRegister(addrSIO+offGPIO, 0) // This does not turn the LED off!
        time.Sleep(time.Second)
    }
}

func writeRegister(reg uintptr, value uint32) {
    ptr := (*uint32)(unsafe.Pointer(reg))
    *ptr = value
    // volatile.StoreUint32(ptr, value)
}
kilograham commented 1 week ago

Please use forums for help: https://forums.raspberrypi.com/viewforum.php?f=143

but no, this is not a silicon bug; you are using the wrong register; 0x14 is the offset of the "SET" register which turns GPIO on per bit set, leaving the others unmodified (so if you write 0, you make no changes)

soypat commented 1 week ago

You are right- sorry for the noise. Using GPIO_OUT register works as expected.