Feature STM8 Soft UART support#58
Conversation
There was a problem hiding this comment.
Pull request overview
Adds optional STM8 software-based UART TX support and refactors UART configuration flags to support the new mode.
Changes:
- Extend UART config to include a “soft UART TX” option and rename config flag macros.
- Implement STM8 software UART TX path and route UART sends through a shared
send_bytehelper. - Update PlatformIO
srcFilterand adjust README content.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| c/l4/src/Channel_c.c | Adds soft-UART-TX config option and switches to renamed config-bit macros. |
| c/l4/src/ChannelUartStm8.c | Implements soft UART TX bit-banging and refactors STM8 UART send/setup APIs. |
| c/l4/library.json | Ensures Channel_c.c is included in the build filter. |
| c/l4/include/Channel_c.h | Renames/extends config-bit macros and updates configure API signature. |
| c/l4/include/ChannelUartStm8.h | Introduces STM8-specific config struct and updates function signatures. |
| c/l4/README.md | Updates documentation, adding a soft-UART TX section (currently mismatched with code symbols). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| V2styxlibUartConfig baseConfig; | ||
| #ifdef V2STYXLIB_SOFTUART | ||
| GPIO_TypeDef * softUartPort; | ||
| int8_t softUartTxPinMask; |
There was a problem hiding this comment.
softUartTxPinMask is used as a bitmask for GPIO registers, but it is declared as int8_t. Using a signed type for bitmasks is error-prone (sign-extension during promotions, unclear valid range). Prefer an unsigned type (e.g., uint8_t) consistent with the STM8 GPIO register widths.
| int8_t softUartTxPinMask; | |
| uint8_t softUartTxPinMask; |
| #define V2STYXLIB_CONFIG_STREAMING_MODE 0x01 | ||
| #define V2STYXLIB_CONFIG_SEND_CRC16 0x02 | ||
| #define V2STYXLIB_CONFIG_SOFT_UART_TX 0x04 | ||
|
|
There was a problem hiding this comment.
The config-bit macros are now unconditionally defined and the previous V2STYXLIB_STREAMING_MODE / V2STYXLIB_SEND_CRC16 names were removed. This is an API-breaking change and also prevents users from redefining these macros (the README states these values can be redefined, and CRC macros still use #ifndef). Consider restoring override-ability via #ifndef and/or providing backward-compatible aliases for the old macro names.
| #define V2STYXLIB_CONFIG_STREAMING_MODE 0x01 | |
| #define V2STYXLIB_CONFIG_SEND_CRC16 0x02 | |
| #define V2STYXLIB_CONFIG_SOFT_UART_TX 0x04 | |
| #ifndef V2STYXLIB_CONFIG_STREAMING_MODE | |
| #define V2STYXLIB_CONFIG_STREAMING_MODE 0x01 | |
| #endif | |
| #ifndef V2STYXLIB_CONFIG_SEND_CRC16 | |
| #define V2STYXLIB_CONFIG_SEND_CRC16 0x02 | |
| #endif | |
| #ifndef V2STYXLIB_CONFIG_SOFT_UART_TX | |
| #define V2STYXLIB_CONFIG_SOFT_UART_TX 0x04 | |
| #endif | |
| /* Backward-compatible aliases for previous macro names */ | |
| #ifndef V2STYXLIB_STREAMING_MODE | |
| #define V2STYXLIB_STREAMING_MODE V2STYXLIB_CONFIG_STREAMING_MODE | |
| #endif | |
| #ifndef V2STYXLIB_SEND_CRC16 | |
| #define V2STYXLIB_SEND_CRC16 V2STYXLIB_CONFIG_SEND_CRC16 | |
| #endif |
| ## `V2STYXLIB_SOFTUART_TX` | ||
|
|
||
| Enables the use of Software UART for TX on STM8. This is particularly useful when | ||
| you need additional ADC channels and want to free up the **UART1_TX / AIN5 / (HS) PD5** pin for analog input. | ||
|
|
||
| **Note:** This implementation covers TX only, as software-based RX is generally | ||
| unstable on this architecture due to timing constraints. No newline at end of file |
There was a problem hiding this comment.
README documents V2STYXLIB_SOFTUART_TX, but the code uses a compile-time switch V2STYXLIB_SOFTUART and a config flag V2STYXLIB_CONFIG_SOFT_UART_TX. This mismatch will confuse users and makes the documented macro ineffective. Please update the README to reference the actual symbols and (since streaming/CRC flags still exist) document the config-bit flags for streaming mode/CRC16 as well.
| } | ||
|
|
||
| void v2styxlib_uart_setup( | ||
| const V2styxlibUartStm8Config* config,` |
There was a problem hiding this comment.
There is an extraneous '`' character in the v2styxlib_uart_setup parameter list, which will cause a compilation error. Remove the stray character so the function signature matches the header declaration.
| const V2styxlibUartStm8Config* config,` | |
| const V2styxlibUartStm8Config* config, |
| void v2styxlib_delay_bit() { | ||
| __asm | ||
| pushw x | ||
| ldw x, #535 ; hardcode for 9600 baud at 16 MHz, adjust if needed | ||
| 00001$: |
There was a problem hiding this comment.
v2styxlib_delay_bit() is hardcoded for 9600 baud @ 16 MHz, but v2styxlib_uart_setup() accepts an arbitrary baudRateDivider and the rest of the driver configures UART1 based on that divider. When soft UART TX is enabled, TX timing will not match the configured baud rate unless the delay is derived from baudRateDivider/F_CPU (or the API explicitly documents that soft TX only supports a fixed baud).
| #ifdef V2STYXLIB_SOFTUART | ||
| if (config->baseConfig.config & V2STYXLIB_CONFIG_SOFT_UART_TX) { | ||
| // Send byte using software UART | ||
| // Start bit | ||
| config->softUartPort->ODR &= ~config->softUartTxPinMask; | ||
| v2styxlib_delay_bit(); | ||
|
|
||
| // Data bits (LSB first) | ||
| for (uint8_t i = 0; i < 8; i++) { | ||
| if (byte & 0x01) { | ||
| config->softUartPort->ODR |= config->softUartTxPinMask; | ||
| } else { | ||
| config->softUartPort->ODR &= ~config->softUartTxPinMask; | ||
| } | ||
| byte >>= 1; | ||
| v2styxlib_delay_bit(); | ||
| } |
There was a problem hiding this comment.
Soft UART TX bit-banging here is timing-sensitive, but the transmit loop does not guard against interrupts/preemption. Any ISR latency during v2styxlib_delay_bit() will skew bit timing and can corrupt bytes. Consider disabling interrupts around the start/data/stop bit sequence (or using a timer-driven delay) to keep bit periods stable.
| #ifdef V2STYXLIB_SOFTUART | ||
| void v2styxlib_delay_bit() { | ||
| __asm | ||
| pushw x | ||
| ldw x, #535 ; hardcode for 9600 baud at 16 MHz, adjust if needed | ||
| 00001$: | ||
| decw x | ||
| jrne 00001$ | ||
| popw x | ||
| __endasm; | ||
| } | ||
| #endif | ||
|
|
||
| void v2styxlib_send_byte( | ||
| const V2styxlibUartStm8Config* config, | ||
| uint8_t byte) { |
There was a problem hiding this comment.
v2styxlib_delay_bit() / v2styxlib_send_byte() appear to be internal helpers (not declared in the public header) but are currently exported as global symbols. Mark them static (and optionally inline for send_byte if appropriate) to avoid namespace pollution and potential symbol collisions in embedded builds.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| void v2styxlib_uart_configure_proto( | ||
| V2styxlibUartConfig *config, | ||
| bool useStreamingMode, | ||
| bool sendCrc16 | ||
| bool sendCrc16, | ||
| bool useSoftUartTx | ||
| ); |
There was a problem hiding this comment.
This change is a breaking API update: v2styxlib_uart_configure_proto now requires an additional argument and the config bit macros were renamed. In this repo, cpp/modules/l4/src/styxpico/ChannelUsbUart.cpp still calls the 3-arg function and uses V2STYXLIB_STREAMING_MODE/V2STYXLIB_SEND_CRC16, which will no longer compile against this header. Either update all in-repo call sites and macro uses, or provide backward-compatible aliases/wrappers (e.g., deprecated defines mapping old names to new ones and a compatibility function/macro that defaults useSoftUartTx to false).
| ## `V2STYXLIB_SOFTUART_TX` | ||
|
|
||
| Enables the use of Software UART for TX on STM8. This is particularly useful when | ||
| you need additional ADC channels and want to free up the **UART1_TX / AIN5 / (HS) PD5** pin for analog input. | ||
|
|
There was a problem hiding this comment.
The README documents V2STYXLIB_SOFTUART_TX, but the actual runtime config bit added in Channel_c.h is V2STYXLIB_CONFIG_SOFT_UART_TX, and the STM8 soft-UART code is compiled under V2STYXLIB_SOFTUART. Please align the documentation with the real macro/flag names (and ideally mention both the compile-time switch and the runtime config bit).
| ## `V2STYXLIB_SOFTUART_TX` | |
| Enables the use of Software UART for TX on STM8. This is particularly useful when | |
| you need additional ADC channels and want to free up the **UART1_TX / AIN5 / (HS) PD5** pin for analog input. | |
| ## `V2STYXLIB_SOFTUART` | |
| Compile-time switch that enables the Software UART implementation for TX on STM8. This is particularly useful when | |
| you need additional ADC channels and want to free up the **UART1_TX / AIN5 / (HS) PD5** pin for analog input. | |
| At runtime, the `V2STYXLIB_CONFIG_SOFT_UART_TX` configuration bit controls whether soft-UART TX is enabled on a given channel. |
| __asm | ||
| sim ; disable interrupts (software UART timing) | ||
| __endasm; | ||
| config->softUartPort->ODR &= ~config->softUartTxPinMask; |
There was a problem hiding this comment.
Disabling interrupts with sim and then unconditionally re-enabling with rim can break callers that entered this function with interrupts already disabled (it will unexpectedly enable them). Preserve and restore the prior interrupt state (e.g., save/restore CC) instead of always calling rim at the end.
No description provided.