Skip to content

Conversation

@schkovich
Copy link
Owner

Update Arduino Pico 4.7.1.

The release enables LIB_PICO_MULTICORE by default and updates Pico SDK to 2.2.0. The release 2.2.0 resolves issues raspberrypi/pico-sdk#2527 and raspberrypi/pico-sdk#2433.

This update simplifies the setup of the test repository and enables using the schkovich/async-tcp@f8eba15 library as a submodule.

schkovich added 30 commits June 5, 2025 10:14
Replace no-op loop1() with active mutex usage through at_time_worker. Core 1
now periodically adds a worker that requires mutex access, while Core 0 tries
to execute_sync. This creates a race condition that triggers an incorrect
assert in async_context_threadsafe_background_execute_sync when Core 0 sees
Core 1 legitimately holding the mutex.

The change proves that the original asserts assumption about mutex ownership
is wrong in a multicore context.
Define a push_state function that allocates a small node for each call
to async_context_threadsafe_background_execute_sync. The node records
the current recursive_mutex_t state (owner and enter_count) and links
into a simple list using head and count variables. This enables
historical inspection of lock_mutex ownership changes.
Replace `sleep_ms(1)` with `sleep_us(777)` in `loop()` to speed up
cycles. Update `c1_counter` trigger from 333 to 33 and change
`sleep_us(100)` to `sleep_us(77)` in `loop1()` for faster execution.
Include gdb-mutex-owner.log and
serial-mutex-owner.log capturing:
GDB session output with breakpoint traces, context dumps
and lock ownership, and timing data in serial log
from the mutex-owner debugging session. These logs support
future troubleshooting and reproducibility.
Update the async-tcp submodule from commit 810dde1 to b0c4056.

This update includes several improvements:
- Modernized code with C++ std::string instead of C-style buffers
- Standardized timestamp functions using time_us_64()
- Improved debug output and error handling
- Fixed include paths and Serial port usage
- Enhanced async context initialization with proper error handling
- Various code style and documentation improvements

The new version maintains compatibility while providing better safety
and more consistent coding patterns throughout the library.

Signed-off-by: Goran Mišković <[email protected]>
Restructure platformio.ini to use a common [env] section for shared configurations
across all environments. This change:

1. Creates an [env] section for common board, framework, platform and upload settings
2. Moves environment-specific configurations to their respective sections
3. Adds proper source file filtering for both test and debug environments
4. Adds missing -DESPHOSTSPI=SPI build flag to both environments
5. Removes redundant configurations from the debug environment
6. Ensures consistent configuration between test and debug builds

The result is a cleaner, more maintainable configuration file with less duplication.

Signed-off-by: Goran Mišković <[email protected]>
…s and enable core debugging

This commit updates the AsyncTCP library submodule to version 6fd6e8c, which implements proper Quote of the Day (QOTD) protocol handling with connection closure as the logical delimiter.
Key changes:
Update lib/async-tcp submodule to latest version
Enable RP2040 core debugging with DEBUG_RP2040_CORE flag
Remove optimization flags (-Og) to improve debugging experience
Remove size optimization flags (-fno-lto) no longer needed with the improved implementation
Remove debug symbols flag (-g) as it's included by default in debug builds
The updated AsyncTCP implementation now correctly handles the QOTD protocol by processing connection closure events as end-of-quote markers, allows incremental quote accumulation, and ensures proper coordination between quote fetching and echo services.

Signed-off-by: Goran Mišković <[email protected]>
This updates the lib/async-tcp pointer from 6fd6e8c to the latest commit, bringing in all recent fixes and refactorings in the async-tcp library.

Signed-off-by: Goran Mišković <[email protected]>
             Delete ContextPayload.h
             Delete SyncPayload.h and SyncPayload.hpp
             Consolidate payload support through SyncBridge's internal SyncPayload struct only.

Signed-off-by: Goran Mišković <[email protected]>
…4cdca506d99b73

Bump async-tcp submodule reference to incorporate recent Worker→PerpetualWorker API refactor and related documentation updates.

Signed-off-by: Goran Mišković <[email protected]>
          Add EchoConnectedHandler, EchoReceivedHandler, IoWrite, MessageBuffer, PrintHandler, QotdConnectedHandler, QotdReceivedHandler, QotdClosedHandler, QuoteBuffer and SerialPrinter into the super project and update includes in main.cpp.

          Bump async-tcp submodule to 48b9ba.

Signed-off-by: Goran Mišković <[email protected]>
       Change #include "Arduino.h" to #include <Arduino.h> in
       src/PrintHandler.cpp
       src/QotdConnectedHandler.cpp.

Signed-off-by: Goran Mišković <[email protected]>
- Move from 3fb80f4 to 075f537
- Includes fix for race condition in cross-core synchronization
- Replaces pico-sdk execute_sync with custom C++ implementation
Move submodule reference to include latest SyncBridge improvements
with re-entrant call detection and recursive mutex support.

Signed-off-by: Goran Mišković <[email protected]>
Remove the atomic busy_guard mechanism from QuoteBuffer::set(), get(),
and append() methods now that SyncBridge provides proper re-entrant
call detection with recursive mutex protection.

Key changes:
- Remove std::atomic<bool> busy_guard member variable
- Remove compare_exchange_strong() checks in all methods
- Simplify method logic to always call execute() directly
- Remove #include <atomic> dependency

The busy_guard was originally protecting against re-entrant calls that
would deadlock on the semaphore mechanism. With the new SyncBridge
implementation using recursive mutex and m_executing flag, this protection
is now handled at the SyncBridge level.

This eliminates the "fail-fast" behavior where concurrent calls would
return empty results, replacing it with proper queuing where all calls
wait for their turn and return actual data.

Benefits:
- Simplified code with fewer synchronization primitives
- Better user experience (no more empty results from concurrent calls)
- Consistent with SyncBridge's re-entrant design
- Reduces memory footprint by removing atomic variable

Signed-off-by: Goran Mišković <[email protected]>
schkovich added 29 commits July 16, 2025 18:48
Implement buffer accumulation to handle cases where quote data arrives
in multiple chunks due to lwIP buffer constraints, even though QOTD
protocol limits quote size.

Changes to EchoReceivedHandler:
- Add m_buffer member to accumulate incoming data chunks
- Replace direct printing with chunk accumulation logic
- Detect END_OF_QUOTE_MARKER across accumulated segments
- Clear both buffer and quote when complete quote is received
- Print complete accumulated quote instead of individual chunks

Related QuoteBuffer changes:
- Add set("") call to clear quote buffer after processing
- Ensure buffer state is reset for next quote cycle

This addresses edge cases where lwIP send buffer free space is smaller
than the quote size, causing fragmented data delivery that needs to be
reassembled before processing.

Note: Work in progress - chunked data handling implementation may need
further refinement based on testing results.

Signed-off-by: Goran Mišković <[email protected]>
Enhance variable naming, resource management, and add monitoring capabilities
to both cores with proper load balancing and connection management.

Key improvements:
- Rename variables for clarity (previous_blue → previous_stack_0, etc.)
- Move qotd_buffer to core 1 for better resource distribution
- Add connection state check to prevent concurrent QOTD connections
- Configure dedicated 16-entry alarm pool for ctx0 to avoid resource contention
- Add proper qotd_buffer.initialize() call in setup1()
- Implement stack statistics monitoring on both cores
- Add heap statistics monitoring with separate intervals
- Replace empty loop1() with actual monitoring workload

This provides better resource utilization across both cores, prevents
connection conflicts, and adds comprehensive system monitoring while
maintaining proper async context isolation between cores.

Changes include:
- Stack stats: Core 0 every 1111ms, Core 1 every 1010ms
- Heap stats: Every 777ms on Core 1
- Connection guard: Check qotd_client.connected() before new connections
- Alarm pool: Custom 16-entry pool for Core 0 context

Signed-off-by: Goran Mišković <[email protected]>
       Bumps async-tcp submodule to db9719a which removes the _sync parameter
       and related functionality from TcpClientContext. This change ensures
       all TCP writes use TCP_WRITE_FLAG_COPY for safety, eliminating the
       dangerous non-copying write mode that could lead to data corruption.

Signed-off-by: Goran Mišković <[email protected]>
       The IoWrite class has been completely removed as it became redundant
       after the async-tcp library refactoring. Originally created to serialize
       blocking-style write operations, IoWrite is no longer needed since:

       - TcpClient::write() now handles async operations directly
       - The sync mode removal eliminated the need for write serialization
       - Direct use of echo_client.write() is simpler and more efficient

       This cleanup removes 131 lines of now-unused synchronization code
       and simplifies the codebase by eliminating an unnecessary abstraction layer.

Signed-off-by: Goran Mišković <[email protected]>
…er.initialize()

             - Switch to direct construction of ContextManager instances for ctx0 and ctx1, following async-tcp library update that removes dependency injection of external async_context_threadsafe_background_t.
             - Remove call to qotd_buffer.initialize(); initialization is now handled in the constructor.

Signed-off-by: Goran Mišković <[email protected]>
             Updated async-tcp submodule to the latest version, which replaces smart pointer-based context management with direct reference (AsyncCtx).
             Refactored all main project code to use the new context reference model, ensuring consistency with the updated async-tcp API.
             This change simplifies context handling, clarifies ownership, and improves code readability throughout the project. No functional changes intended.

Signed-off-by: Goran Mišković <[email protected]>
… for robustness

               Transitioned from time-based to counter-based event triggering to reduce system load and improve test realism. Replaced unsafe use of TcpClient::connected() with an explicit qotd_in_progress flag to ensure safe, single-connection management and avoid concurrency issues with LwIP. These changes make the integration test more reliable and better aligned with the actual constraints of the networking stack.

Signed-off-by: Goran Mišković <[email protected]>
…col correctness

               The marker was unnecessary since the QOTD protocol guarantees a complete quote on connection close. This change simplifies the flow, reduces ambiguity, and makes the code more robust and maintainable.

Signed-off-by: Goran Mišković <[email protected]>
…plement empty/clear methods

               Removed unnecessary m_buffer.clear() from QuoteBuffer constructor, as std::string is default-initialized to empty.
               Added thread-safe empty() and clear() methods to QuoteBuffer for checking and resetting buffer content.
               Updated documentation for new methods

Signed-off-by: Goran Mišković <[email protected]>
…nter

                       Eliminated the use of std::atomic<bool> print_lock and related locking logic from SerialPrinter.</bool>
                       Simplified the print() method to directly invoke PrintHandler::create without contention checks.
                       Updated method signature to be const-correct.

Signed-off-by: Goran Mišković <[email protected]>
…sage for improved clarity and control

                              Removed unnecessary inclusion of QuoteBuffer and buffer clearing from EchoReceivedHandler.
                              Simplified get_quote_of_the_day(): now always requests a new quote if not already in progress, and clears the buffer after initiating a connection.
                              Refactored get_echo() to use a new echo_connected flag and send quotes only when data is available, improving connection logic.
                              Split scheduler into scheduler0 (Core 0) and scheduler1 (Core 1) for clearer timing management; updated all related code to use the correct scheduler.
                              Adjusted timing intervals for scheduled tasks to new values.
                              Improved comments and removed redundant checks for buffer emptiness before requesting new quotes.

Signed-off-by: Goran Mišković <[email protected]>
…ear/append with set in QOTD workflow

                         Removed qotd_buffer.clear() from get_quote_of_the_day to avoid unnecessary empty state.
                         Changed m_quote_buffer.append(data) to m_quote_buffer.set(data) in QotdReceivedHandler, ensuring the buffer is atomically updated with new data.

Signed-off-by: Goran Mišković <[email protected]>
… to echoed quote, switch to Serial1.print.

- EchoReceivedHandler: Always append a newline to the echoed quote before printing, ensuring each log entry has its own line, and making the log easily parseable. Moved peekConsume after print for clarity.
- PrintHandler: Use Serial1.print instead of println, as log entries now include their own trailing newline.

Signed-off-by: Goran Mišković <[email protected]>
…erations using LED_BUILTIN.

- SerialPrinter: Set LED_BUILTIN HIGH before scheduling a print operation to indicate print activity.
- PrintHandler: Set LED_BUILTIN LOW after printing to signal completion of the print operation.

Signed-off-by: Goran Mišković <[email protected]>
…Nagle's algorithm configuration from QOTD connection.

- A connection to the QOTD server only receives data, and the server closes the connection after transmission.
- No need to configure keep-alive or Nagle's algorithm for this connection.
- Simplified QotdConnectedHandler to reflect protocol requirements.

Signed-off-by: Goran Mišković <[email protected]>
- Introduced readBoardTemperature() and formatTemperatureMessage() utilities.
- Added print_board_temperature() to log formatted temperature readings via SerialPrinter.
- Registered board temperature as a scheduled entry in scheduler1 and print it periodically in loop1.
- Adjusted scheduler intervals and initialised LED_BUILTIN as output.

Signed-off-by: Goran Mišković <[email protected]>
…e feedback.

- Prefix all informational, debug, and error log messages with standardized tags (e.g., [INFO], [DEBUG], [ERROR]) in EchoConnectedHandler, QotdConnectedHandler, and main.cpp.
= Update runtime serial notifications to use consistent log prefixes.
- Adjust scheduler entry intervals for improved timing consistency.
- Enhance error and status reporting for QOTD and ECHO client connections.

Signed-off-by: Goran Mišković <[email protected]>
…latform_packages.

- Split platform_packages configuration for default, staging, test and dev environments.
- Assign specific framework-arduinopico sources and versions per environment.
- Remove redundant, now default `-DLIB_PICO_MULTICORE=1` build flag.
- Improve clarity and maintainability of environment-specific settings.

Signed-off-by: Goran Mišković <[email protected]>
- Point async-tcp submodule to f8eba155, which restores correct ownership transfer in ephemeral_bridging_function and fixes a use-after-free caused by a previous bad merge.
- All other changes are minor doc and formatting updates.

Signed-off-by: Goran Mišković <[email protected]>
- Change DEBUG_RP2040_PORT to Serial in the dev environment to route debug output to USB CDC, which is not thread-safe.
- Application output remains on Serial1, strictly managed by async context on core 1 for thread safety.
- Update main.cpp to initialize Serial (USB CDC) without baud rate and add a short timeout for a robust startup.
- Ensures clear separation between thread-safe application output and non-thread-safe debug output.

Signed-off-by: Goran Mišković <[email protected]>
…reference async-tcp usage.

- Rewrite README to reflect the evolution from pico-sdk-tests to async-tcp-tests, now focused on async-tcp library development and testing.
- Simplify setup instructions: users now only need to clone the repo, initialize submodules, and build/monitor with PlatformIO.
- Direct users to the async-tcp submodule README for new project integration details.
- Update project structure and notes for clarity.

Signed-off-by: Goran Mišković <[email protected]>
…ation.

- Replace the generic docs directory reference in README.md with a direct link to the new Application Workflow (docs/workflow.md) for clearer project guidance.
- Add docs/workflow.md to the repository to document the application's architecture, concurrency model, and operational flow.

Signed-off-by: Goran Mišković <[email protected]>
@schkovich schkovich merged commit 6c8eb04 into master Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants