Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions src/rp2040/adc.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ADC functions on rp2040
//
// Copyright (C) 2021 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2021-2025 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.

Expand All @@ -10,6 +10,7 @@
#include "hardware/structs/adc.h" // adc_hw
#include "hardware/structs/padsbank0.h" // padsbank0_hw
#include "hardware/structs/resets.h" // RESETS_RESET_ADC_BITS
#include "hardware/structs/sysinfo.h" // sysinfo_hw
#include "internal.h" // enable_pclock
#include "sched.h" // sched_shutdown

Expand All @@ -21,7 +22,19 @@ DECL_ENUMERATION("pin", "ADC_TEMPERATURE", ADC_TEMPERATURE_PIN);
struct gpio_adc
gpio_adc_setup(uint32_t pin)
{
if ((pin < 26 || pin > 29) && pin != ADC_TEMPERATURE_PIN)
uint32_t min_gpio = 26, max_gpio = 29, adc_temp_chan = 4;
#if CONFIG_MACH_RP2350
// Check for rp2350b package
if (!is_enabled_pclock(RESETS_RESET_SYSINFO_BITS))
enable_pclock(RESETS_RESET_SYSINFO_BITS);
if (!(sysinfo_hw->package_sel & SYSINFO_PACKAGE_SEL_BITS)) {
min_gpio = 40;
max_gpio = 47;
adc_temp_chan = 8;
}
#endif

if ((pin < min_gpio || pin > max_gpio) && pin != ADC_TEMPERATURE_PIN)
shutdown("Not a valid ADC pin");

// Enable the ADC
Expand All @@ -32,10 +45,10 @@ gpio_adc_setup(uint32_t pin)

uint8_t chan;
if (pin == ADC_TEMPERATURE_PIN) {
chan = 4;
chan = adc_temp_chan;
adc_hw->cs |= ADC_CS_TS_EN_BITS;
} else {
chan = pin - 26;
chan = pin - min_gpio;
padsbank0_hw->io[pin] = PADS_BANK0_GPIO0_OD_BITS;
}

Expand Down
62 changes: 40 additions & 22 deletions src/rp2040/gpio.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// GPIO functions on rp2040
//
// Copyright (C) 2021 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2021-2025 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.

Expand All @@ -19,12 +19,16 @@
* Pin mappings
****************************************************************/

DECL_ENUMERATION_RANGE("pin", "gpio0", 0, 30);
#define NUM_GPIO (CONFIG_MACH_RP2040 ? 30 : 48)

DECL_ENUMERATION_RANGE("pin", "gpio0", 0, NUM_GPIO);

// Set the mode and extended function of a pin
void
gpio_peripheral(uint32_t gpio, int func, int pull_up)
{
if (gpio >= NUM_GPIO)
shutdown("Not a valid pin");
padsbank0_hw->io[gpio] = (
PADS_BANK0_GPIO0_IE_BITS
| (PADS_BANK0_GPIO0_DRIVE_VALUE_4MA << PADS_BANK0_GPIO0_DRIVE_MSB)
Expand All @@ -35,9 +39,12 @@ gpio_peripheral(uint32_t gpio, int func, int pull_up)

// Convert a register and bit location back to an integer pin identifier
static int
mask_to_pin(uint32_t mask)
mask_to_pin(void *sio, uint32_t mask)
{
return ffs(mask)-1;
int pin = ffs(mask)-1;
if (CONFIG_MACH_RP2350 && sio != (void*)sio_hw)
pin += 32;
return pin;
}


Expand All @@ -48,30 +55,35 @@ mask_to_pin(uint32_t mask)
struct gpio_out
gpio_out_setup(uint8_t pin, uint8_t val)
{
if (pin >= 30)
goto fail;
struct gpio_out g = { .bit=1<<pin };
if (pin >= NUM_GPIO)
shutdown("Not a valid pin");
void *sio = (void*)sio_hw;
if (CONFIG_MACH_RP2350 && pin >= 32) {
pin -= 32;
sio += 4;
}
struct gpio_out g = { .sio=sio, .bit=1<<pin };
gpio_out_reset(g, val);
return g;
fail:
shutdown("Not an output pin");
}

void
gpio_out_reset(struct gpio_out g, uint8_t val)
{
int pin = mask_to_pin(g.bit);
int pin = mask_to_pin(g.sio, g.bit);
irqstatus_t flag = irq_save();
gpio_out_write(g, val);
sio_hw->gpio_oe_set = g.bit;
sio_hw_t *sio = g.sio;
sio->gpio_oe_set = g.bit;
gpio_peripheral(pin, 5, 0);
irq_restore(flag);
}

void
gpio_out_toggle_noirq(struct gpio_out g)
{
sio_hw->gpio_togl = g.bit;
sio_hw_t *sio = g.sio;
sio->gpio_togl = g.bit;
}

void
Expand All @@ -83,37 +95,43 @@ gpio_out_toggle(struct gpio_out g)
void
gpio_out_write(struct gpio_out g, uint8_t val)
{
sio_hw_t *sio = g.sio;
if (val)
sio_hw->gpio_set = g.bit;
sio->gpio_set = g.bit;
else
sio_hw->gpio_clr = g.bit;
sio->gpio_clr = g.bit;
}


struct gpio_in
gpio_in_setup(uint8_t pin, int8_t pull_up)
{
if (pin >= 30)
goto fail;
struct gpio_in g = { .bit=1<<pin };
if (pin >= NUM_GPIO)
shutdown("Not a valid pin");
void *sio = (void*)sio_hw;
if (CONFIG_MACH_RP2350 && pin >= 32) {
pin -= 32;
sio += 4;
}
struct gpio_in g = { .sio=sio, .bit=1<<pin };
gpio_in_reset(g, pull_up);
return g;
fail:
shutdown("Not an input pin");
}

void
gpio_in_reset(struct gpio_in g, int8_t pull_up)
{
int pin = mask_to_pin(g.bit);
int pin = mask_to_pin(g.sio, g.bit);
irqstatus_t flag = irq_save();
gpio_peripheral(pin, 5, pull_up);
sio_hw->gpio_oe_clr = g.bit;
sio_hw_t *sio = g.sio;
sio->gpio_oe_clr = g.bit;
irq_restore(flag);
}

uint8_t
gpio_in_read(struct gpio_in g)
{
return !!(sio_hw->gpio_in & g.bit);
sio_hw_t *sio = g.sio;
return !!(sio->gpio_in & g.bit);
}
2 changes: 2 additions & 0 deletions src/rp2040/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <stdint.h> // uint32_t

struct gpio_out {
void *sio;
uint32_t bit;
};
struct gpio_out gpio_out_setup(uint8_t pin, uint8_t val);
Expand All @@ -13,6 +14,7 @@ void gpio_out_toggle(struct gpio_out g);
void gpio_out_write(struct gpio_out g, uint8_t val);

struct gpio_in {
void *sio;
uint32_t bit;
};
struct gpio_in gpio_in_setup(uint8_t pin, int8_t pull_up);
Expand Down
Loading