Skip to content
Snippets Groups Projects
Select Git revision
  • 41b4d3adb41dc161b6027240a1eb88e452ece0d9
  • master default protected
  • develop
  • lurch-patch-2
  • int_frac
  • lurch-patch-1
  • more_board_header_checks
  • best_effort_wfe
  • bi-pins-order-assert
  • 1274-blocking-uart-transmission-appears-to-exit-early
  • iar/develop
  • use_nvic
  • new_pico_rand_api
  • tinyusb-1.5.0
  • lwip_deps
  • tusb_bump2
  • pico_rand
  • misc_headers_issues
  • tusb_bump
  • remove_memset_of_stuct
  • recursive_mutex_cxx
  • 2.0.0
  • 1.5.1
  • 1.5.0
  • 1.4.0
  • 1.3.1
  • 1.3.0
  • 1.2.0
  • 1.1.2
  • 1.1.1
  • 1.1.0
  • 1.0.1
  • 1.0.0
33 results

gpio.c

Blame
  • gpio.c 9.79 KiB
    /*
     * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
     *
     * SPDX-License-Identifier: BSD-3-Clause
     */
    
    #include "hardware/gpio.h"
    #include "hardware/sync.h"
    
    #include "hardware/structs/iobank0.h"
    #include "hardware/irq.h"
    
    #if LIB_PICO_BINARY_INFO
    #include "pico/binary_info.h"
    #endif
    
    static gpio_irq_callback_t callbacks[NUM_CORES];
    // a 1 bit means the IRQ is handled by a raw IRQ handler
    static uint32_t raw_irq_mask[NUM_CORES];
    
    // Get the raw value from the pin, bypassing any muxing or overrides.
    int gpio_get_pad(uint gpio) {
        check_gpio_param(gpio);
        hw_set_bits(&padsbank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
        return (iobank0_hw->io[gpio].status & IO_BANK0_GPIO0_STATUS_INFROMPAD_BITS)
                >> IO_BANK0_GPIO0_STATUS_INFROMPAD_LSB;
    }
    
    /// \tag::gpio_set_function[]
    // Select function for this GPIO, and ensure input/output are enabled at the pad.
    // This also clears the input/output/irq override bits.
    void gpio_set_function(uint gpio, enum gpio_function fn) {
        check_gpio_param(gpio);
        invalid_params_if(GPIO, ((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS);
        // Set input enable on, output disable off
        hw_write_masked(&padsbank0_hw->io[gpio],
                       PADS_BANK0_GPIO0_IE_BITS,
                       PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS
        );
        // Zero all fields apart from fsel; we want this IO to do what the peripheral tells it.
        // This doesn't affect e.g. pullup/pulldown, as these are in pad controls.
        iobank0_hw->io[gpio].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
    }
    /// \end::gpio_set_function[]
    
    enum gpio_function gpio_get_function(uint gpio) {
        check_gpio_param(gpio);
        return (enum gpio_function) ((iobank0_hw->io[gpio].ctrl & IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS) >> IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB);
    }
    
    // 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(
                &padsbank0_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
        );
    }
    
    // Direct override for per-GPIO IRQ signal
    void gpio_set_irqover(uint gpio, uint value) {
        check_gpio_param(gpio);
        hw_write_masked(&iobank0_hw->io[gpio].ctrl,
                       value << IO_BANK0_GPIO0_CTRL_IRQOVER_LSB,
                       IO_BANK0_GPIO0_CTRL_IRQOVER_BITS
        );
    }