Unable to use compiler defines to define pioasm values #757

Open
opened 2022-03-14 05:08:40 -05:00 by essele · 10 comments
essele commented 2022-03-14 05:08:40 -05:00 (Migrated from github.com)

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.

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 <pin>) 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.
lurch commented 2022-03-14 05:25:04 -05:00 (Migrated from github.com)

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)

> 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)
essele commented 2022-03-14 09:05:24 -05:00 (Migrated from github.com)

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.

> 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.
lurch commented 2022-03-14 09:45:49 -05:00 (Migrated from github.com)

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 ?

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` ?
essele commented 2022-03-14 10:30:32 -05:00 (Migrated from github.com)

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.

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.
lurch commented 2022-03-14 11:00:17 -05:00 (Migrated from github.com)

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 🤷‍♂️

> 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:
kilograham commented 2023-02-07 08:01:07 -06:00 (Migrated from github.com)

consider for 1.6.0

consider for 1.6.0
visenri commented 2025-03-09 15:44:19 -05:00 (Migrated from github.com)

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.

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.
lurch commented 2025-03-10 03:54:22 -05:00 (Migrated from github.com)

@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?

@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?
visenri commented 2025-04-01 15:55:51 -05:00 (Migrated from github.com)

@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](https://github.com/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](https://github.com/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:** ```c #define TEST_VALUE (2 + 1) ... set x, TEST_VALUE ``` **INVALID:** ```c #define TEST_VALUE (1 > 0) ... set x, TEST_VALUE ``` _error: invalid character: > in set x, (1 > 0)_
visenri commented 2025-04-01 16:04:44 -05:00 (Migrated from github.com)

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.

Aside from that consideration, you can use the preprocessor as long as you keep the syntax valid. **VALID:** ```c #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. ```c #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** ```c #include "myConfig.h" ... wait 1 gpio MY_GPIO_PIN ``` **Global compiler definitions are also available:** **CMakeLists.txt** ```c target_compile_definitions(${PROJECT_NAME} PRIVATE PICO_DEFAULT_UART_RX_PIN=1 ... ``` **In myProgram.pio** ```c 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.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk#757
No description provided.