1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
52
53
54
55
56
60
61
62
63
71
72
73
80
81
82
89
90
97
98
105
106
113
114
115
119
120
127
128
134
135
136
137
138
145
146
152
153
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
207
208
220
221
226
227
232
233
236
237
240
241
246
247
252
253
258
259
263
264
265
272
273
280
281
286
287
290
291
299
300
308
309
/* ... */
#include "hardware/gpio.h"
#include "hardware/sync.h"
#include "hardware/structs/io_bank0.h"
#include "hardware/irq.h"
#if LIB_PICO_BINARY_INFO
#include "pico/binary_info.h"
#endif
static gpio_irq_callback_t callbacks[NUM_CORES];
#if NUM_BANK0_GPIOS > 32
typedef uint64_t raw_irq_mask_type_t;
#else
typedef uint32_t raw_irq_mask_type_t;
#endif
static raw_irq_mask_type_t raw_irq_mask[NUM_CORES];
int gpio_get_pad(uint gpio) {
check_gpio_param(gpio);
hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
return (io_bank0_hw->io[gpio].status & IO_BANK0_GPIO0_STATUS_INFROMPAD_BITS)
>> IO_BANK0_GPIO0_STATUS_INFROMPAD_LSB;
}{ ... }
void gpio_set_function(uint gpio, gpio_function_t fn) {
check_gpio_param(gpio);
invalid_params_if(HARDWARE_GPIO, ((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS);
hw_write_masked(&pads_bank0_hw->io[gpio],
PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS
);
io_bank0_hw->io[gpio].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
#if !PICO_RP2040
hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_ISO_BITS);/* ... */
#endif
}{ ... }
gpio_function_t gpio_get_function(uint gpio) {
check_gpio_param(gpio);
return (gpio_function_t) ((io_bank0_hw->io[gpio].ctrl & IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS) >> IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB);
}{ ... }
void gpio_set_pulls(uint gpio, bool up, bool down) {
check_gpio_param(gpio);
hw_write_masked(
&pads_bank0_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
);
}{ ... }
void gpio_set_irqover(uint gpio, uint value) {
check_gpio_param(gpio);
hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_IRQOVER_LSB,
IO_BANK0_GPIO0_CTRL_IRQOVER_BITS
);
}{ ... }
void gpio_set_inover(uint gpio, uint value) {
check_gpio_param(gpio);
hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_INOVER_LSB,
IO_BANK0_GPIO0_CTRL_INOVER_BITS
);
}{ ... }
void gpio_set_outover(uint gpio, uint value) {
check_gpio_param(gpio);
hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_OUTOVER_LSB,
IO_BANK0_GPIO0_CTRL_OUTOVER_BITS
);
}{ ... }
void gpio_set_oeover(uint gpio, uint value) {
check_gpio_param(gpio);
hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_OEOVER_LSB,
IO_BANK0_GPIO0_CTRL_OEOVER_BITS
);
}{ ... }
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled) {
check_gpio_param(gpio);
if (enabled)
hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
else
hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
}{ ... }
bool gpio_is_input_hysteresis_enabled(uint gpio) {
check_gpio_param(gpio);
return (pads_bank0_hw->io[gpio] & PADS_BANK0_GPIO0_SCHMITT_BITS) != 0;
}{ ... }
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew) {
check_gpio_param(gpio);
hw_write_masked(&pads_bank0_hw->io[gpio],
(uint)slew << PADS_BANK0_GPIO0_SLEWFAST_LSB,
PADS_BANK0_GPIO0_SLEWFAST_BITS
);
}{ ... }
enum gpio_slew_rate gpio_get_slew_rate(uint gpio) {
check_gpio_param(gpio);
return (enum gpio_slew_rate)((pads_bank0_hw->io[gpio]
& PADS_BANK0_GPIO0_SLEWFAST_BITS)
>> PADS_BANK0_GPIO0_SLEWFAST_LSB);
}{ ... }
static_assert(PADS_BANK0_GPIO0_DRIVE_VALUE_8MA == GPIO_DRIVE_STRENGTH_8MA, "");
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive) {
check_gpio_param(gpio);
hw_write_masked(&pads_bank0_hw->io[gpio],
(uint)drive << PADS_BANK0_GPIO0_DRIVE_LSB,
PADS_BANK0_GPIO0_DRIVE_BITS
);
}{ ... }
enum gpio_drive_strength gpio_get_drive_strength(uint gpio) {
check_gpio_param(gpio);
return (enum gpio_drive_strength)((pads_bank0_hw->io[gpio]
& PADS_BANK0_GPIO0_DRIVE_BITS)
>> PADS_BANK0_GPIO0_DRIVE_LSB);
}{ ... }
static void gpio_default_irq_handler(void) {
uint core = get_core_num();
gpio_irq_callback_t callback = callbacks[core];
io_bank0_irq_ctrl_hw_t *irq_ctrl_base = core ? &io_bank0_hw->proc1_irq_ctrl : &io_bank0_hw->proc0_irq_ctrl;
for (uint gpio = 0; gpio < NUM_BANK0_GPIOS; gpio+=8) {
uint32_t events8 = irq_ctrl_base->ints[gpio >> 3u];
for(uint i=gpio;events8 && i<gpio+8;i++) {
uint32_t events = events8 & 0xfu;
if (events && !(raw_irq_mask[core] & (1ull << i))) {
gpio_acknowledge_irq(i, events);
if (callback) {
callback(i, events);
}if (callback) { ... }
}if (events && !(raw_irq_mask[core] & (1ull << i))) { ... }
events8 >>= 4;
}for (uint i=gpio;events8 && i
}for (uint gpio = 0; gpio < NUM_BANK0_GPIOS; gpio+=8) { ... }
}{ ... }
static void _gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled, io_bank0_irq_ctrl_hw_t *irq_ctrl_base) {
gpio_acknowledge_irq(gpio, events);
io_rw_32 *en_reg = &irq_ctrl_base->inte[gpio / 8];
events <<= 4 * (gpio % 8);
if (enabled)
hw_set_bits(en_reg, events);
else
hw_clear_bits(en_reg, events);
}{ ... }
void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled) {
assert(!enabled
|| (raw_irq_mask[get_core_num()] & (1u<<gpio))
|| callbacks[get_core_num()]);
io_bank0_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
&io_bank0_hw->proc1_irq_ctrl : &io_bank0_hw->proc0_irq_ctrl;
_gpio_set_irq_enabled(gpio, events, enabled, irq_ctrl_base);
}{ ... }
void gpio_set_irq_enabled_with_callback(uint gpio, uint32_t events, bool enabled, gpio_irq_callback_t callback) {
gpio_set_irq_callback(callback);
gpio_set_irq_enabled(gpio, events, enabled);
if (enabled) irq_set_enabled(IO_IRQ_BANK0, true);
}{ ... }
void gpio_set_irq_callback(gpio_irq_callback_t callback) {
uint core = get_core_num();
if (callbacks[core]) {
if (!callback) {
irq_remove_handler(IO_IRQ_BANK0, gpio_default_irq_handler);
}if (!callback) { ... }
callbacks[core] = callback;
}if (callbacks[core]) { ... } else if (callback) {
callbacks[core] = callback;
irq_add_shared_handler(IO_IRQ_BANK0, gpio_default_irq_handler, GPIO_IRQ_CALLBACK_ORDER_PRIORITY);
}else if (callback) { ... }
}{ ... }
void gpio_add_raw_irq_handler_with_order_priority_masked(uint32_t gpio_mask, irq_handler_t handler, uint8_t order_priority) {
hard_assert(!(raw_irq_mask[get_core_num()] & gpio_mask));
raw_irq_mask[get_core_num()] |= gpio_mask;
irq_add_shared_handler(IO_IRQ_BANK0, handler, order_priority);
}{ ... }
void gpio_add_raw_irq_handler_with_order_priority_masked64(uint64_t gpio_mask, irq_handler_t handler, uint8_t order_priority) {
hard_assert(!(raw_irq_mask[get_core_num()] & gpio_mask));
raw_irq_mask[get_core_num()] |= (raw_irq_mask_type_t) gpio_mask;
irq_add_shared_handler(IO_IRQ_BANK0, handler, order_priority);
}{ ... }
void gpio_add_raw_irq_handler_masked(uint32_t gpio_mask, irq_handler_t handler) {
gpio_add_raw_irq_handler_with_order_priority_masked(gpio_mask, handler, GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
}{ ... }
void gpio_add_raw_irq_handler_masked64(uint64_t gpio_mask, irq_handler_t handler) {
gpio_add_raw_irq_handler_with_order_priority_masked64(gpio_mask, handler, GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
}{ ... }
void gpio_remove_raw_irq_handler_masked(uint32_t gpio_mask, irq_handler_t handler) {
assert(raw_irq_mask[get_core_num()] & gpio_mask);
irq_remove_handler(IO_IRQ_BANK0, handler);
raw_irq_mask[get_core_num()] &= ~gpio_mask;
}{ ... }
void gpio_remove_raw_irq_handler_masked64(uint64_t gpio_mask, irq_handler_t handler) {
assert(raw_irq_mask[get_core_num()] & gpio_mask);
irq_remove_handler(IO_IRQ_BANK0, handler);
raw_irq_mask[get_core_num()] &= (raw_irq_mask_type_t)~gpio_mask;
}{ ... }
void gpio_set_dormant_irq_enabled(uint gpio, uint32_t events, bool enabled) {
check_gpio_param(gpio);
io_bank0_irq_ctrl_hw_t *irq_ctrl_base = &io_bank0_hw->dormant_wake_irq_ctrl;
_gpio_set_irq_enabled(gpio, events, enabled, irq_ctrl_base);
}{ ... }
void gpio_acknowledge_irq(uint gpio, uint32_t events) {
check_gpio_param(gpio);
io_bank0_hw->intr[gpio / 8] = events << (4 * (gpio % 8));
}{ ... }
#define DEBUG_PIN_MASK (((1u << PICO_DEBUG_PIN_COUNT)-1) << PICO_DEBUG_PIN_BASE)
void gpio_debug_pins_init(void) {
gpio_init_mask(DEBUG_PIN_MASK);
gpio_set_dir_masked(DEBUG_PIN_MASK, DEBUG_PIN_MASK);
#if LIB_PICO_BINARY_INFO
bi_decl_if_func_used(bi_pin_mask_with_names(DEBUG_PIN_MASK, "Debug"));
#endif
}{ ... }
void gpio_set_input_enabled(uint gpio, bool enabled) {
check_gpio_param(gpio);
if (enabled)
hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
else
hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
}{ ... }
void gpio_init(uint gpio) {
gpio_set_dir(gpio, GPIO_IN);
gpio_put(gpio, 0);
gpio_set_function(gpio, GPIO_FUNC_SIO);
}{ ... }
void gpio_deinit(uint gpio) {
gpio_set_function(gpio, GPIO_FUNC_NULL);
}{ ... }
void gpio_init_mask(uint gpio_mask) {
for(uint i=0;i<NUM_BANK0_GPIOS;i++) {
if (gpio_mask & 1) {
gpio_init(i);
}if (gpio_mask & 1) { ... }
gpio_mask >>= 1;
}for (uint i=0;i
}{ ... }
void gpio_set_function_masked(uint32_t gpio_mask, gpio_function_t fn) {
for (uint i = 0; i < MIN(NUM_BANK0_GPIOS, 32u); i++) {
if (gpio_mask & 1u) {
gpio_set_function(i, fn);
}if (gpio_mask & 1u) { ... }
gpio_mask >>= 1;
}for (uint i = 0; i < MIN(NUM_BANK0_GPIOS, 32u); i++) { ... }
}{ ... }
void gpio_set_function_masked64(uint64_t gpio_mask, gpio_function_t fn) {
for (uint i = 0; i < MIN(NUM_BANK0_GPIOS, 64u); i++) {
if (gpio_mask & 1u) {
gpio_set_function(i, fn);
}if (gpio_mask & 1u) { ... }
gpio_mask >>= 1;
}for (uint i = 0; i < MIN(NUM_BANK0_GPIOS, 64u); i++) { ... }
}{ ... }