pico-sdk icon indicating copy to clipboard operation
pico-sdk copied to clipboard

Unable to use compiler defines to define pioasm values

Open essele opened this issue 3 years ago • 10 comments

I have created a library where the definitions of which pins to use are controlled by compiler defines in the CMakeLists.txt file.

For most of the pins used by my various PIO programs this works fine as they are set in the initialisation code and therefore the code has access to the defines as it forms part of the .pio.h file (or even in the main body of the code.)

However, one pin that I wait on is a gpio pin (wait 0 gpio ) and therefore this is directly referenced in the PIO code, which does not have access to any of the compiler defines, so I cannot work out a clean way to be able to control this from the make file.

Suggestions on the forum include using the C preprocessor, which makes sense, but has issues as the pioasm syntax isn't particularly compatible. I've also looked at adding support for command line defines to pioasm, but that's also not clean as the complete list of compiler defines would probably also include non integer values which would need to be ignored.

So there doesn't seem to be a clean way to do this, at the moment I'm hardcoding that value into the pio files, but this make the library difficult to use by others.

essele avatar Mar 14 '22 10:03 essele

However, one pin that I wait on is a gpio pin (wait 0 gpio ) and therefore this is directly referenced in the PIO code, which

I assume there's some reason you can't use wait 0 pin ?

does not have access to any of the compiler defines, so I cannot work out a clean way to be able to control this from the make file.

Section 3.3.1 of https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf talks about .define ( PUBLIC ) <symbol> <value> - does that not do what you want? (Apologies if that's a stupid question, but I've not used pioasm myself)

lurch avatar Mar 14 '22 10:03 lurch

I assume there's some reason you can't use wait 0 pin ?

It's potentially possible, but the particular pin is one that has a gpout clock generated, so it's limited already, if I have to make it part of a consecutive sequence of other in-pins then it becomes very restrictive. I haven't actually tried to see if it's even possible.

Section 3.3.1 of https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf talks about .define ( PUBLIC ) <symbol> <value> - does that not do what you want? (Apologies if that's a stupid question, but I've not used pioasm myself)

This is kind of the wrong way around ... it allows you to define something in the pio file that's then available in the .h file. I want to define everything in the make file (as per PICO_DEFAULT_UART_TX_PIN for example) and then have it usable in the pio file.

essele avatar Mar 14 '22 14:03 essele

Ahhh. So perhaps the most sensible option would be to add a pioasm flag that'd allow you to override a defined symbol? e.g. if you had .define WAIT_PIN 3 in your .pio file, and then invoked pioasm -DWAIT_PIN=5 ... it'd behave as though you'd specified .define WAIT_PIN 5 ?

lurch avatar Mar 14 '22 14:03 lurch

Yes, that's one approach (and I did get a quick proof of concept working) but I would argue it doesn't need to necessarily override an existing value, it could create a completely new one.

However ... you then still need a way to pass the relevant defines to that process in the make file ... the easiest approach is to pass all of the COMPILER_DEFINITIONS, however this then would include non-integer based defines which would need to be excluded/ignored ... so still messy and somewhat counter-intuitive.

I actually prefer the idea that you used the C preprocessor to pre-process the file, that way any macros can be handled relatively cleanly ... however that doesn't work well with the syntax of pio files as it stands. Hence my concern about a lack of an obvious approach.

essele avatar Mar 14 '22 15:03 essele

however this then would include non-integer based defines which would need to be excluded/ignored

That's why I was suggesting only overriding existing .define directives - that way e.g. pioasm -DPICO_SDK_PATH=../../pico-sdk ... would just be ignored (because there'd be no .define PICO_SDK_PATH 2 in the .pio file), and you'd still have the "default" .define WAIT_PIN 3 being used. (no need for #ifndef etc.) But it sounds like you might have more experience with preprocessors and COMPILER_DEFINITIONS than me, so there might be subtleties that I'm overlooking :man_shrugging:

lurch avatar Mar 14 '22 16:03 lurch

consider for 1.6.0

kilograham avatar Feb 07 '23 14:02 kilograham

Using "pico_generate_pio_header_pre" as I've implemented here: https://github.com/visenri/pico_cmake_extras allows the use of all c preprocessor features.

So it can be used to include other files or use preprocessor macros defined elsewhere.

@kilograham: This should be easy to integrate into the next SDK release.

visenri avatar Mar 09 '25 20:03 visenri

@visenri As already mentioned, I don't have much familiarity with preprocessors, but just out of curiosity how does your approach address the "that doesn't work well with the syntax of pio files as it stands" concern that @essele mentioned above?

lurch avatar Mar 10 '25 08:03 lurch

@visenri As already mentioned, I don't have much familiarity with preprocessors, but just out of curiosity how does your approach address the "that doesn't work well with the syntax of pio files as it stands" concern that @essele mentioned above?

@lurch: I don't know what @essele was concerned about, maybe he/she meant that expressions defined in a preprocessor macro may not be valid for pio expressions, you must take into account that expressions used must be valid for pio asm:

VALID:

#define TEST_VALUE (2 + 1)
...
set x, TEST_VALUE

INVALID:

#define TEST_VALUE (1 > 0)
...
set x, TEST_VALUE

error: invalid character: > in set x, (1 > 0)

visenri avatar Apr 01 '25 20:04 visenri

Aside from that consideration, you can use the preprocessor as long as you keep the syntax valid.

VALID:

#define TEST_VALUE (1 > 0)
...
#if TEST_VALUE != 0 
    set x, 1
#else
    set x, 0
#endif

Including a configuration file: "myConfig.h" Preprocessor stuff only or "c" specific stuff hiding it using preprocessor macro __PIO_ASM_COMPILER This file can be included in both c/c++ and pio files.

#define MY_GPIO_PIN 1
#ifndef __PIO_ASM_COMPILER
    // c stuff can be used here, the pio asm compiler will not see this section.
#endif

In myProgram.pio

#include "myConfig.h"
...
wait 1 gpio MY_GPIO_PIN

Global compiler definitions are also available: CMakeLists.txt

target_compile_definitions(${PROJECT_NAME} PRIVATE
  PICO_DEFAULT_UART_RX_PIN=1
...

In myProgram.pio

wait 0 gpio PICO_DEFAULT_UART_RX_PIN

When you understand how the preprocessor works, and what is valid syntax for pio asm there should be no problem or conflict.

visenri avatar Apr 01 '25 21:04 visenri