17#include "gpio_rp2040.h"
22using namespace _IO_BANK0_;
23using namespace _PADS_BANK0_;
25function<void()> gpio_rp2040::_intHandler[30] {
nullptr};
26uint8_t gpio_rp2040::_irqConfig [30] {0};
28gpio_rp2040::gpio_rp2040(gpio_pin_t gpio)
33void gpio_rp2040::setGpio(gpio_pin_t gpio) {
36 _mask = 1 << (gpio % 32);
39gpio_pin_t gpio_rp2040::getGpio()
const {
44gpio_rp2040::gpioMode (uint16_t mode) {
46 setSEL (GPIO_CTRL_FUNCSEL__sio);
51gpio_rp2040::gpioRead ()
const {
53 return SIO.GPIO_IN & _mask;
57gpio_rp2040::gpioWrite (
bool value) {
60 if (value) SIO.GPIO_OE_CLR = _mask;
61 else SIO.GPIO_OE_SET = _mask;
63 else if (_open_source) {
64 if (value) SIO.GPIO_OE_SET = _mask;
65 else SIO.GPIO_OE_CLR = _mask;
69 if (value) SIO.GPIO_OUT_SET = _mask;
70 else SIO.GPIO_OUT_CLR = _mask;
75gpio_rp2040::gpioToggle () {
77 if (_open_drain || _open_source)
78 SIO.GPIO_OE_XOR = _mask;
79 else SIO.GPIO_OUT_XOR = _mask;
83gpio_rp2040::gpioAttachIrq (gpio_mode_t mode,
84 function<
void()> handler) {
86 _irqConfig[_gpio] = 0;
88 if (mode & GPIO::LEVEL_LOW) {
89 _irqConfig[_gpio] |= 0x1;
91 if (mode & GPIO::LEVEL_HIGH) {
92 _irqConfig[_gpio] |= 0x2;
94 if (mode & GPIO::FALLING) {
95 _irqConfig[_gpio] |= 0x4;
97 if (mode & GPIO::RISING) {
98 _irqConfig[_gpio] |= 0x8;
101 _intHandler[_gpio] = handler;
107gpio_rp2040::gpioDetachIrq () {
112 _intHandler[_gpio] = 0;
116gpio_rp2040::gpioEnableIrq () {
118 PROC0_INTE0_t *INTE_SET = &IO_BANK0_SET.PROC0_INTE0 + (_gpio >> 3) + (SIO.CPUID*12);
119 INTR0_t *INTR = &IO_BANK0.INTR0 + (_gpio >> 3) + (SIO.CPUID*12);
120 int mask_shift = (_gpio & 0x7) * 4;
123 NVIC_DisableIRQ(IO_IRQ_BANK0_IRQn);
125 *INTE_SET = _irqConfig[_gpio] << mask_shift;
127 *INTR = (0xf << mask_shift);
129 NVIC_ClearPendingIRQ(IO_IRQ_BANK0_IRQn);
130 NVIC_EnableIRQ (IO_IRQ_BANK0_IRQn);
134gpio_rp2040::gpioDisableIrq () {
136 PROC0_INTE0_t *INTE_CLR = &IO_BANK0_CLR.PROC0_INTE0 + (_gpio >> 3) + (SIO.CPUID*12);
137 INTR0_t *INTR = &IO_BANK0.INTR0 + (_gpio >> 3);
138 int mask_shift = (_gpio & 0x7) * 4;
140 *INTR = (0xf << mask_shift);
142 *INTE_CLR = (0xf << mask_shift);
145void gpio_rp2040::setSEL (uint8_t sel) {
147 GPIO_CTRL_t *io_ctrl = &IO_BANK0.GPIO0_CTRL + (_gpio << 1);
149 io_ctrl->FUNCSEL = sel;
150 io_ctrl->OUTOVER = 0;
153 io_ctrl->IRQOVER = 0;
156void gpio_rp2040::setMode (uint16_t mode) {
158 GPIO_t *pad_ctrl = &PADS_BANK0.GPIO[_gpio];
162 _open_source =
false;
164 SIO.GPIO_OUT_CLR = _mask;
165 SIO.GPIO_OE_CLR = _mask;
169 pad_ctrl->DRIVE = GPIO_DRIVE__2mA;
172 pad_ctrl->SCHMITT = 1;
173 pad_ctrl->SLEWFAST = 0;
175 if (mode & GPIO::INPUT) {
178 if (mode & GPIO::INPUT_INVERT) {
180 GPIO_CTRL_t *io_ctrl = &IO_BANK0.GPIO0_CTRL + (_gpio << 1);
181 io_ctrl->INOVER = GPIO_CTRL_INOVER__INVERT;
183 if (mode & GPIO::OUTPUT) {
184 SIO.GPIO_OE_SET = _mask;
186 if (mode & GPIO::OUTPUT_OPEN_DRAIN) {
188 SIO.GPIO_OE_SET = _mask;
190 if (mode & GPIO::OUTPUT_OPEN_SOURCE) {
192 SIO.GPIO_OUT_SET = _mask;
194 if (mode & GPIO::PULLUP) {
197 if (mode & GPIO::PULLDOWN) {
200 if (mode & GPIO::FAST) {
201 pad_ctrl->SLEWFAST = 1;
203 if ((mode & GPIO::DRIVE_4mA) || (mode & GPIO::DRIVE_8mA)) {
204 pad_ctrl->DRIVE = (mode >> 10) & 0x3;
206 if (mode & GPIO::INIT_HIGH) {
209 if (mode & GPIO::INIT_LOW) {
218void IO_IRQ_BANK0_Handler(
void) {
219 PROC0_INTS0_t *INTS = &IO_BANK0.PROC0_INTS0 + (SIO.CPUID*12);
220 INTR0_t *INTR = &IO_BANK0.INTR0;
221 for (
int i=0; i < 4; ++i, INTS++, INTR++) {
222 while (uint8_t pos = __builtin_ffs(*INTS)) {
224 *INTR = (1 << --pos);
226 uint16_t gpio = (pos >> 2) + (i << 3);
227 gpio_rp2040::_intHandler[gpio]();
CMSIS-Core(M) Device Peripheral Access Layer Header File for Device RP2040.