Home > OS >  Creating an IRQ for the Raspberry Pi Pico works in C but not C ?
Creating an IRQ for the Raspberry Pi Pico works in C but not C ?

Time:12-13

When I compile this code in C it runs perfectly but when I try to compile it in C it sends an error which I'll add below. I've tried declaring the function with every variable type I could think of which didn't change anything. I also searched online but found nothing that helped.

Code:

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"

void gpio_callback() {
    printf("GPIO RISE\n");
}

int main() {
    stdio_init_all();

    printf("Hello GPIO IRQ\n");
    gpio_set_irq_enabled_with_callback(2, GPIO_IRQ_EDGE_RISE, true, &gpio_callback);

    // Wait forever
    while (1);

    return 0;
}

My CMakeFile.txt for C :

cmake_minimum_required(VERSION 3.19)

include(pico_sdk_import.cmake)

project(hello_gpio_irq)

pico_sdk_init()

add_executable(hello_gpio_irq hello_gpio_irq.cpp)

pico_enable_stdio_usb(hello_gpio_irq 1)
pico_enable_stdio_uart(hello_gpio_irq 0)

# pull in common dependencies
target_link_libraries(hello_gpio_irq pico_stdlib)

# create map/bin/hex file etc.
pico_add_extra_outputs(hello_gpio_irq)

My CmakeLists.txt for C:

cmake_minimum_required(VERSION 3.19)

include(pico_sdk_import.cmake)

project(hello_gpio_irq)

pico_sdk_init()

add_executable(hello_gpio_irq hello_gpio_irq.c)

pico_enable_stdio_usb(hello_gpio_irq 1)
pico_enable_stdio_uart(hello_gpio_irq 0)

# pull in common dependencies
target_link_libraries(hello_gpio_irq pico_stdlib)

# create map/bin/hex file etc.
pico_add_extra_outputs(hello_gpio_irq)

Compiler output for C :

[main] Building folder: hello_gpio_irq 
[build] Starting build
[proc] Executing command: /usr/bin/cmake --build /home/taylor/Documents/Programs/Pi-Pico/hello_gpio_irq/build --config Debug --target all --
[build] [2/8  12% :: 0.025] Performing build step for 'ELF2UF2Build'
[build] ninja: no work to do.
[build] [3/8  25% :: 0.057] Performing build step for 'PioasmBuild'
[build] ninja: no work to do.
[build] [4/8  37% :: 0.071] No install step for 'ELF2UF2Build'
[build] [5/8  50% :: 0.110] No install step for 'PioasmBuild'
[build] [6/8  62% :: 0.149] Completed 'ELF2UF2Build'
[build] [7/8  75% :: 0.155] Completed 'PioasmBuild'
[build] [7/8  87% :: 0.267] Building CXX object CMakeFiles/hello_gpio_irq.dir/hello_gpio_irq.cpp.obj
[build] FAILED: CMakeFiles/hello_gpio_irq.dir/hello_gpio_irq.cpp.obj 
[build] /usr/bin/arm-none-eabi-g   -DCFG_TUSB_DEBUG=1 -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DCFG_TUSB_OS=OPT_OS_PICO -DLIB_PICO_BIT_OPS=1 -DLIB_PICO_BIT_OPS_PICO=1 -DLIB_PICO_DIVIDER=1 -DLIB_PICO_DIVIDER_HARDWARE=1 -DLIB_PICO_DOUBLE=1 -DLIB_PICO_DOUBLE_PICO=1 -DLIB_PICO_FIX_RP2040_USB_DEVICE_ENUMERATION=1 -DLIB_PICO_FLOAT=1 -DLIB_PICO_FLOAT_PICO=1 -DLIB_PICO_INT64_OPS=1 -DLIB_PICO_INT64_OPS_PICO=1 -DLIB_PICO_MALLOC=1 -DLIB_PICO_MEM_OPS=1 -DLIB_PICO_MEM_OPS_PICO=1 -DLIB_PICO_PLATFORM=1 -DLIB_PICO_PRINTF=1 -DLIB_PICO_PRINTF_PICO=1 -DLIB_PICO_RUNTIME=1 -DLIB_PICO_STANDARD_LINK=1 -DLIB_PICO_STDIO=1 -DLIB_PICO_STDIO_USB=1 -DLIB_PICO_STDLIB=1 -DLIB_PICO_SYNC=1 -DLIB_PICO_SYNC_CORE=1 -DLIB_PICO_SYNC_CRITICAL_SECTION=1 -DLIB_PICO_SYNC_MUTEX=1 -DLIB_PICO_SYNC_SEM=1 -DLIB_PICO_TIME=1 -DLIB_PICO_UNIQUE_ID=1 -DLIB_PICO_UTIL=1 -DPICO_BOARD=\"pico\" -DPICO_BUILD=1 -DPICO_CMAKE_BUILD_TYPE=\"Debug\" -DPICO_COPY_TO_RAM=0 -DPICO_CXX_ENABLE_EXCEPTIONS=0 -DPICO_NO_FLASH=0 -DPICO_NO_HARDWARE=0 -DPICO_ON_DEVICE=1 -DPICO_TARGET_NAME=\"hello_gpio_irq\" -DPICO_USE_BLOCKED_RAM=0 -I/home/taylor/pico/pico-sdk/src/common/pico_stdlib/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_gpio/include -I/home/taylor/pico/pico-sdk/src/common/pico_base/include -I/home/taylor/Documents/Programs/Pi-Pico/hello_gpio_irq/build/generated/pico_base -I/home/taylor/pico/pico-sdk/src/boards/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_platform/include -I/home/taylor/pico/pico-sdk/src/rp2040/hardware_regs/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_base/include -I/home/taylor/pico/pico-sdk/src/rp2040/hardware_structs/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_claim/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_sync/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_irq/include -I/home/taylor/pico/pico-sdk/src/common/pico_sync/include -I/home/taylor/pico/pico-sdk/src/common/pico_time/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_timer/include -I/home/taylor/pico/pico-sdk/src/common/pico_util/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_uart/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_divider/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_runtime/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_clocks/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_resets/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_pll/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_vreg/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_watchdog/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_xosc/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_printf/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_bootrom/include -I/home/taylor/pico/pico-sdk/src/common/pico_bit_ops/include -I/home/taylor/pico/pico-sdk/src/common/pico_divider/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_double/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_int64_ops/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_float/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_malloc/include -I/home/taylor/pico/pico-sdk/src/rp2_common/boot_stage2/include -I/home/taylor/pico/pico-sdk/src/common/pico_binary_info/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_stdio/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_stdio_usb/include -I/home/taylor/pico/pico-sdk/lib/tinyusb/src -I/home/taylor/pico/pico-sdk/lib/tinyusb/src/common -I/home/taylor/pico/pico-sdk/lib/tinyusb/hw -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/include -I/home/taylor/pico/pico-sdk/src/rp2_common/pico_unique_id/include -I/home/taylor/pico/pico-sdk/src/rp2_common/hardware_flash/include -I/home/taylor/pico/pico-sdk/src/common/pico_usb_reset_interface/include -mcpu=cortex-m0plus -mthumb -Og -g -ffunction-sections -fdata-sections -fno-exceptions -fno-unwind-tables -fno-rtti -fno-use-cxa-atexit -MD -MT CMakeFiles/hello_gpio_irq.dir/hello_gpio_irq.cpp.obj -MF CMakeFiles/hello_gpio_irq.dir/hello_gpio_irq.cpp.obj.d -o CMakeFiles/hello_gpio_irq.dir/hello_gpio_irq.cpp.obj -c /home/taylor/Documents/Programs/Pi-Pico/hello_gpio_irq/hello_gpio_irq.cpp
[build] /home/taylor/Documents/Programs/Pi-Pico/hello_gpio_irq/hello_gpio_irq.cpp: In function 'int main()':
[build] /home/taylor/Documents/Programs/Pi-Pico/hello_gpio_irq/hello_gpio_irq.cpp:13:69: error: invalid conversion from 'void (*)()' to 'gpio_irq_callback_t' {aka 'void (*)(unsigned int, long unsigned int)'} [-fpermissive]
[build]    13 |     gpio_set_irq_enabled_with_callback(2, GPIO_IRQ_EDGE_RISE, true, &gpio_callback);
[build]       |                                                                     ^~~~~~~~~~~~~~
[build]       |                                                                     |
[build]       |                                                                     void (*)()
[build] In file included from /home/taylor/pico/pico-sdk/src/common/pico_stdlib/include/pico/stdlib.h:13,
[build]                  from /home/taylor/Documents/Programs/Pi-Pico/hello_gpio_irq/hello_gpio_irq.cpp:2:
[build] /home/taylor/pico/pico-sdk/src/rp2_common/hardware_gpio/include/hardware/gpio.h:440:107: note:   initializing argument 4 of 'void gpio_set_irq_enabled_with_callback(uint, uint32_t, bool, gpio_irq_callback_t)'
[build]   440 | void gpio_set_irq_enabled_with_callback(uint gpio, uint32_t event_mask, bool enabled, gpio_irq_callback_t callback);
[build]       |                                                                                       ~~~~~~~~~~~~~~~~~~~~^~~~~~~~
[build] ninja: build stopped: subcommand failed.
[proc] The command: /usr/bin/cmake --build /home/taylor/Documents/Programs/Pi-Pico/hello_gpio_irq/build --config Debug --target all -- exited with code: 1 and signal: null
[build] Build finished with exit code 1

CodePudding user response:

void gpio_set_irq_enabled_with_callback (uint gpio, 
                                         uint32_t event_mask, 
                                         bool enabled,  
                                         gpio_irq_callback_t callback)

expects a gpio_irq_callback_t for the final parameter, and gpio_irq_callback_t looks like

typedef void(* gpio_irq_callback_t) (uint gpio, uint32_t event_mask)

so gpio_set_irq_enabled_with_callback expects

void gpio_callback() {
    printf("GPIO RISE\n");
}

to be

void gpio_callback(uint /*gpio*/, uint32_t /*event_mask*/) {
    printf("GPIO RISE\n");
}

You can uncomment the parameter names when you choose to use them. Until you do, you'll likely get unused parameter warnings.

This only looks like it works in C because C will compile it. You'll probably get a warning if you turn them up loud enough because there are no guarantees that it will behave correctly at runtime. Depending on the calling convention the results could be catastrophic. For example, if the callee is responsible for popping the parameters off the stack, void () doesn't expect parameters and won't pop anything. The two parameters the caller pushed onto the stack will sit there, throwing the stack off and screwing everything up in unpredictable ways. C is much more anally retentive about matching types and rejects the function outright, so you get a compiler error instead of a warning or the program freaking out at runtime.

Do NOT attempt to fix this with a cast. You'll likely only change the compiler in for unusual behaviour at runtime.

  • Related