Skip to content

Commit 6c8eb04

Browse files
authored
Merge pull request #1 from schkovich/pico-sdk-2.2.0-update
Having `LIB_PICO_MULTICORE` enabled by default, and issues raspberrypi/pico-sdk#2527 and raspberrypi/pico-sdk#2433 allowed setting the schkovich/async-tcp@f8eba15 library as a submodule.
2 parents 6e8abbd + d69713a commit 6c8eb04

34 files changed

+2526
-140
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "lib/async-tcp"]
2+
path = lib/async-tcp
3+
url = [email protected]:schkovich/async-tcp.git

README.md

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,50 @@
1-
# Development Setup Guide
1+
# async-tcp-tests
22

3-
This project uses arduino-pico core for debugging RP2040-based Arduino Pico programs with local modifications.
3+
This repository was initially set as a testbed for debugging and validating fixes for two bugs in the Raspberry Pi Pico SDK. Over time, it evolved into a dedicated environment for developing and testing the async-tcp library.
44

5-
## Prerequisites
5+
## Current Purpose
66

7-
- [Arduino Pico](https://github.com/earlephilhower/arduino-pico) core
8-
- [PlatformIO](https://platformio.org/)
9-
- CMSIS-DAP compatible debug probe
7+
The repository is now focused on testing and demonstrating the async-tcp library, which provides an event-driven, thread-safe TCP client abstraction for the RP2040 platform using async_context and lwIP.
108

11-
## Setup Process
9+
## Quick Start
1210

13-
1. Clone those repositories:
14-
```bash
15-
git clone https://github.com/schkovich/arduino-pico.git
16-
cd arduino-pico
17-
git checkout execute_sync_2433
18-
git submodule update --init
19-
cd ..
20-
git clone [email protected]:schkovich/pico-sdk-tests.git
21-
cd pico-sdk-tests
22-
```
11+
To evaluate or build this project:
2312

24-
## Project Structure
25-
```plaintext
13+
1. **Clone this repository:**
2614

27-
├── arduino-pico # Forked arduino-pico core
28-
├── pico-sdk-tests
29-
│   ├── lib
30-
│   ├── .pio # PlatformIO build directory
31-
│   ├── scripts # Debug scripts
32-
│   └── src
33-
```
15+
```sh
16+
git clone https://github.com/schkovich/async-tcp-tests.git
17+
cd async-tcp-tests
18+
```
3419

35-
## Project configuration
36-
The arduino-pico core is configured in [platformio.ini](https://docs.platformio.org/en/latest/projectconf/index.html#platformio-ini-project-configuration-file) via [platform_package](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform_packages.html#platform-packages) option, pointing to the [local folder](https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_install.html#local-folder) and “Symbolic Link” feature:
37-
```ini
38-
[env:debug]
39-
board = nanorp2040connect
40-
framework = arduino
41-
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
42-
board_build.core = earlephilhower
43-
platform_packages =
44-
framework-arduinopico@symlink://../arduino-pico
45-
```
46-
## Building Core Components
47-
The pico-sdk build process:
20+
2. **Initialise and update submodules:**
21+
22+
```sh
23+
git submodule update --init --recursive
24+
```
4825

49-
1. Compiles core SDK libraries
50-
2. Generates boot stage 2 code for different flash chips
51-
3. Produces required build artifacts for both RP2040 and RP2350
26+
3. **Build and monitor with PlatformIO:**
5227

53-
For detailed build steps, see [make-libpico.sh](https://github.com/schkovich/arduino-pico/blob/execute-sync%407c51742/tools/libpico/make-libpico.sh) in the arduino-pico core.
28+
```sh
29+
pio run
30+
pio device monitor
31+
```
32+
33+
For instructions on using async-tcp in a new project, see the [async-tcp README](lib/async-tcp/README.md).
34+
35+
## Project Structure
36+
37+
```plaintext
38+
├── lib
39+
│   └── async-tcp # async-tcp library as a submodule
40+
├── scripts # Debug scripts
41+
├── src # Application source code
42+
└── docs # Documentation
43+
```
5444

55-
### Development Workflow
45+
## Notes
46+
- The repo was formerly named `pico-sdk-tests`.
47+
- The original pico-sdk bugfixes are now upstream and no longer require local patching.
48+
- The async-tcp library is under active development and testing here.
5649

57-
- Pico SDK and async_context are pre-built statically linked to the project
58-
- The project is built using [PlatformIO](https://docs.platformio.org/en/latest/core/index.html)
59-
- Debug using CMSIS-DAP probe
50+
For more details, see The [Application Workflow](docs/workflow.md).

docs/WriteEvents.puml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@startuml Write Events Flow
2+
3+
participant "App Code\n(Core 0)" as App
4+
participant "TcpClient" as Client
5+
participant "TcpWriteHandler\n(EventBridge)" as Handler
6+
participant "async_context\n(Core 0)" as Context
7+
participant "TcpClientContext" as TcpCtx
8+
participant "lwIP TCP" as TCP
9+
participant "Network" as Net
10+
11+
== Write Request ==
12+
App -> Client: write_async(data, size)
13+
Client -> Handler: enqueue_write(data, size)
14+
Handler -> Context: run() [schedule onWork()]
15+
Context -> Handler: onWork()
16+
Handler -> TcpCtx: write(data, size)
17+
TcpCtx -> TCP: tcp_write()
18+
TCP -> Net: send packet
19+
20+
== ACK Reception ==
21+
Net -> TCP: ACK received
22+
TCP -> TcpCtx: _acked(len)
23+
TcpCtx -> Handler: on_ack_received(len)
24+
Handler -> Context: run() [schedule onWork()]
25+
Context -> Handler: onWork()
26+
27+
alt More data to send
28+
Handler -> TcpCtx: write(remaining_data)
29+
TcpCtx -> TCP: tcp_write()
30+
TCP -> Net: send next chunk
31+
@enduml

docs/uar-2433-log-analysis.md

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
## Memory Layout Context
44

55
### RP2040 Stack Configuration
6+
67
- Each Cortex M0+ core has its own stack
78
- Stacks grow downward from high to low addresses
89
- Default configuration:
9-
- Single core: 8KB stack for core 0
10-
- Dual core: 4KB per core (shared from same 8KB)
11-
- Stacks placed in separate scratch banks (X/Y) for performance
10+
- Single core: 8KB stack for core 0
11+
- Dual core: 4KB per core (shared from same 8KB)
12+
- Stacks placed in separate scratch banks (X/Y) for performance
1213
- In our case: `bool core1_separate_stack = true;` gives each core 8KB
1314

1415
### Stack Usage Analysis
16+
1517
- Worker struct allocated at 0x20041f74
1618
- Printf buffer pushing against worker memory
1719
- Critical 48-byte alignment causing corruption
@@ -20,13 +22,15 @@
2022
## Debugging Setup
2123

2224
### 1. Timestamp Collection
25+
2326
```cpp
2427
timestamp_enter = to_us_since_boot(get_absolute_time());
2528
const auto rc = async_context_execute_sync(&async_ctx.core, do_some_work, &ref_counter);
2629
timestamp_exit = to_us_since_boot(get_absolute_time());
2730
```
2831

2932
### 2. GDB Instrumentation
33+
3034
```gdb
3135
break async_context_base_execute_once
3236
commands
@@ -46,6 +50,7 @@ end
4650
## Findings
4751

4852
### 1. Stack Memory Pattern
53+
4954
```
5055
0x20041f74 (Worker struct location):
5156
|-------------------|
@@ -61,6 +66,7 @@ Printf buffer (grows down)
6166
```
6267

6368
### 2. Serial Output and Memory Impact
69+
6470
```
6571
// String lengths affecting stack layout
6672
Cycle 9: "Counter 9; ..." // 47 chars, stack safe
@@ -69,6 +75,7 @@ Cycle 11: "[Counter 11]..." // 48 chars, fatal alignment
6975
```
7076

7177
### 3. Memory Corruption Pattern
78+
7279
```
7380
Initial state (cycle 1):
7481
- work_pending corrupted (1->232)
@@ -83,15 +90,17 @@ Fatal state (cycle 11):
8390
```
8491

8592
### 4. Stack Layout Analysis
93+
8694
- Worker struct (16 bytes) at 0x20041f74
8795
- Printf buffer allocated above worker
8896
- 48-byte boundary critical because:
89-
1. Stack is 8-byte aligned
90-
2. Printf buffer rounded up for alignment
91-
3. Counter digits affect buffer size
92-
4. At 48 bytes, buffer end perfectly aligns with worker start
97+
1. Stack is 8-byte aligned
98+
2. Printf buffer rounded up for alignment
99+
3. Counter digits affect buffer size
100+
4. At 48 bytes, buffer end perfectly aligns with worker start
93101

94102
### 5. Crash Analysis
103+
95104
```asm
96105
// Fatal access in async_context_base_execute_once during list traversal:
97106
0x1000a7be: ldr r3, [r5, #4] // Try to read next field from corrupted worker (0xa)
@@ -108,21 +117,23 @@ r0 = 0x20001560 // async_context pointer
108117
```
109118

110119
## Key Insights
120+
111121
1. Stack Layout Significance:
112-
- 8KB per core (due to core1_separate_stack = true)
113-
- Stack alignment requirements affect corruption pattern
114-
- Worker struct position relative to printf buffer critical
122+
- 8KB per core (due to core1_separate_stack = true)
123+
- Stack alignment requirements affect corruption pattern
124+
- Worker struct position relative to printf buffer critical
115125

116126
2. UAR Manifestation:
117-
- work_pending corrupted to 232 immediately (early warning)
118-
- next field corrupted to 0xa when string hits 48 bytes
119-
- Crash happens when trying to traverse corrupted linked list
120-
- Fatal because of invalid memory access (0xa is not a valid address)
127+
- work_pending corrupted to 232 immediately (early warning)
128+
- next field corrupted to 0xa when string hits 48 bytes
129+
- Crash happens when trying to traverse corrupted linked list
130+
- Fatal because of invalid memory access (0xa is not a valid address)
121131

122132
3. Corruption Chain:
123-
- Printf buffer (48 bytes) overwrites worker struct
124-
- Worker still in linked list but memory reused
125-
- Next traversal attempts to dereference 0xa
126-
- System crashes trying to read from invalid address
133+
- Printf buffer (48 bytes) overwrites worker struct
134+
- Worker still in linked list but memory reused
135+
- Next traversal attempts to dereference 0xa
136+
- System crashes trying to read from invalid address
127137

128-
This analysis shows how a stack-based UAR vulnerability manifests through linked list corruption, where the crash occurs during list traversal rather than during worker execution.
138+
This analysis shows how a stack-based UAR vulnerability manifests through linked list corruption, where the crash occurs
139+
during list traversal rather than during worker execution.

0 commit comments

Comments
 (0)