aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Balbi <[email protected]>2025-11-13 09:58:21 -0800
committerGitHub <[email protected]>2025-11-13 09:58:21 -0800
commitf4b8ae36bec40a15bedd3c0493e4822f9c5238dd (patch)
tree2b989f04f7bd2778e4763116181b6571a3a6efea
parentf53d4975774dd0c6009ad72692f394dca1083c0b (diff)
Remove a lot of text from README.md (#15)
New text will be added as necessary. Co-authored-by: Felipe Balbi <[email protected]>
-rw-r--r--README.md357
1 files changed, 2 insertions, 355 deletions
diff --git a/README.md b/README.md
index 86c0413f0..6e7d61c0e 100644
--- a/README.md
+++ b/README.md
@@ -1,366 +1,13 @@
1# Embassy MCXA276 HAL 1# Embassy MCXA256 HAL
2 2
3[![check](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/check.yml/badge.svg)](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/check.yml) 3[![check](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/check.yml/badge.svg)](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/check.yml)
4[![no-std](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/nostd.yml/badge.svg)](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/nostd.yml) 4[![no-std](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/nostd.yml/badge.svg)](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/nostd.yml)
5[![rolling](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/rolling.yml/badge.svg)](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/rolling.yml) 5[![rolling](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/rolling.yml/badge.svg)](https://github.com/OpenDevicePartnership/embassy-mcxa/actions/workflows/rolling.yml)
6 6
7A Hardware Abstraction Layer (HAL) for the NXP MCXA276 microcontroller 7A Hardware Abstraction Layer (HAL) for the NXP MCXA256 microcontroller
8using the Embassy async framework. This HAL provides safe, idiomatic 8using the Embassy async framework. This HAL provides safe, idiomatic
9Rust interfaces for GPIO, UART, and OSTIMER peripherals. 9Rust interfaces for GPIO, UART, and OSTIMER peripherals.
10 10
11## Prerequisites
12
13### Ubuntu/Debian Setup
14
15```bash
16# Install Rust toolchain
17curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
18source ~/.cargo/env
19
20# Add target for MCXA276 (ARM Cortex-M33)
21rustup target add thumbv8m.main-none-eabihf
22
23# Install required tools
24sudo apt update
25sudo apt install -y gdb-multiarch curl wget
26
27# Install probe-rs for running and debugging
28cargo install probe-rs --features cli
29```
30
31### Windows Setup
32
33- Install Rust via https://rustup.rs (default options are fine)
34- Add the MCXA276 target:
35 ```powershell
36 rustup target add thumbv8m.main-none-eabihf
37 ```
38- Install probe-rs CLI (we will use it directly; no GDB required):
39 ```powershell
40 cargo install probe-rs --features cli
41 ```
42- Install a serial terminal (e.g., Tera Term): https://ttssh2.osdn.jp/
43- USB drivers: Windows 10/11 usually picks up the board as a USB CDC device automatically (COM port)
44
45### Hardware Requirements
46
47- NXP FRDM-MCXA276 development board
48- Debug probe (CMSIS-DAP compatible)
49- USB cable for power and programming
50
51## Examples
52
53This HAL includes several examples demonstrating different peripherals:
54
55### GPIO Examples
56
57#### `blink`
58Blinks an LED connected to GPIO pin. Demonstrates basic GPIO output operations.
59
60### UART Examples
61
62#### `hello`
63Interactive UART2 demo: prints a banner and supports `help`, `echo <text>`, `hex <byte>`.
64
65### OSTIMER Examples
66
67#### `ostimer_alarm`
68
69Demonstrates setting and waiting for OSTIMER alarms.
70
71#### `ostimer_async`
72Shows asynchronous OSTIMER operations with Embassy's async runtime.
73
74#### `ostimer_counter`
75Demonstrates OSTIMER counter functionality.
76
77#### `ostimer_race_test`
78Advanced example testing OSTIMER race conditions and synchronization.
79
80### RTC Example
81
82#### `rtc_alarm`
83Demonstrates how to enable and use the RTC to generate an interrupt after 10seconds.
84
85## Build and Run
86
87### Using probe-rs
88
89All examples require specifying your debug probe. First, find your probe ID:
90
91```bash
92probe-rs list
93```
94
95Then run examples with your probe ID (replace `1fc9:0143:H3AYDQVQMTROB` with your actual probe):
96
97```bash
98# GPIO blink example
99PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "gpio ostimer0" --example blink
100
101
102
103# UART hello example
104PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 ostimer0" --example hello
105
106# OSTIMER examples
107PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 ostimer0" --example ostimer_alarm
108PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 ostimer0" --example ostimer_async
109PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 ostimer0" --example ostimer_counter
110PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 ostimer0" --example ostimer_race_test
111
112# RTC example
113PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 rtc0" --example rtc_alarm
114```
115
116**Note:** All examples run from RAM, not flash memory. They are loaded directly into RAM for faster development iteration.
117
118**Important:** After pressing the RESET button on the board, the first `cargo run` attempt may fail with a connection error. This is expected - simply run the command again and it will work. The run.sh script now properly sets the Vector Table Offset Register (VTOR) to point to the RAM-based vector table, ensuring the correct stack pointer and reset vector are used.
119
120```console
121smw016108@smw016108:~/Downloads/nxp/rust/uart/embassy-mcxa276$ PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --release --features "gpio ostimer0" --example blink
122 Finished `release` profile [optimized + debuginfo] target(s) in 0.07s
123 Running `/home/smw016108/Downloads/nxp/rust/uart/embassy-mcxa276/./run.sh target/thumbv8m.main-none-eabihf/release/examples/blink`
124probe-rs gdb server failed to connect to target. Log:
125----- probe-rs gdb log -----
126 Error: Connecting to the chip was unsuccessful.
127
128 Caused by:
129 0: An ARM specific error occurred.
130 1: Error using access port FullyQualifiedApAddress { dp: Default, ap: V1(0) }.
131 2: Failed to read register DRW at address 0xd0c
132 3: An error occurred in the communication with an access port or debug port.
133 4: Target device responded with a FAULT response to the request.
134smw016108@smw016108:~/Downloads/nxp/rust/uart/embassy-mcxa276$ PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --release --features "gpio ostimer0" --example blink
135 Finished `release` profile [optimized + debuginfo] target(s) in 0.02s
136 Running `/home/smw016108/Downloads/nxp/rust/uart/embassy-mcxa276/./run.sh target/thumbv8m.main-none-eabihf/release/examples/blink`
137```
138
139### Additional UART Examples
140
141#### `uart_interrupt`
142Interrupt-driven UART2 echo. Type in the serial terminal; each byte is echoed back from the IRQ handler path.
143
144#### `lpuart_polling`
145Blocking TX/RX echo over UART2 using the simple polling driver.
146
147#### `lpuart_buffered`
148Async buffered driver with separate TX/RX tasks; echoes typed characters in chunks.
149
150Pins: UART2 TX=P2_2, RX=P2_3 (ALT3), 115200 8N1.
151
152### ADC Examples
153
154#### `adc_polling`
155Configures ADC1 channel A8 (pin P1_10) and prints conversion values to UART2 periodically.
156
157#### `adc_interrupt`
158Triggers a conversion and signals completion via ADC1 interrupt, printing a notification on UART2.
159
160```console
1610x20002040 in ?? ()
162Supported Commands:
163
164 info - print session information
165 reset - reset target
166 reset halt - reset target and halt afterwards
167
168Loading section .vector_table, size 0x224 lma 0x20000000
169Loading section .text, size 0x97e lma 0x20000224
170Loading section .Reset, size 0x58 lma 0x20000ba4
171Loading section .rodata, size 0x28 lma 0x20000bfc
172Start address 0x20000ba4, load size 3106
173Transfer rate: 13 KB/sec, 776 bytes/write.
174```
175
176then I see the LED blinking. I press CTRL+C to exit. It will show me ^C
177
178```console
179Program received signal SIGINT, Interrupt.
1800x20000880 in embassy_executor::arch::thread::Executor::run<blink::__cortex_m_rt_main::{closure_env#0}> (self=0x200027e8, init=...) at /home/smw016108/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/embassy-executor-0.9.1/src/arch/cortex_m.rs:106
181106 asm!("wfe");
182[Inferior 1 (process 1) detached]
183Program loaded and started (no reset)
184smw016108@smw016108:~/Downloads/nxp/rust/uart/embassy-mcxa276$ \
185
186Then I press RESET again and I want to run another example, like ostimer_alarm. I open the console using sudo picocom -b 115200 /dev/ttyACM0 and I start running the example:
187
188smw016108@smw016108:~/Downloads/nxp/rust/uart/embassy-mcxa276$ PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 ostimer0" --example ostimer_alarm
189 Finished `dev` profile [optimized + debuginfo] target(s) in 0.02s
190 Running `/home/smw016108/Downloads/nxp/rust/uart/embassy-mcxa276/./run.sh target/thumbv8m.main-none-eabihf/debug/examples/ostimer_alarm`
191probe-rs gdb server failed to connect to target. Log:
192----- probe-rs gdb log -----
193 Error: Connecting to the chip was unsuccessful.
194
195 Caused by:
196 0: An ARM specific error occurred.
197 1: Error using access port FullyQualifiedApAddress { dp: Default, ap: V1(0) }.
198 2: Failed to read register DRW at address 0xd0c
199 3: An error occurred in the communication with an access port or debug port.
200 4: Target device responded with a FAULT response to the request.
201smw016108@smw016108:~/Downloads/nxp/rust/uart/embassy-mcxa276$ PROBE=1fc9:0143:H3AYDQVQMTROB cargo run --features "lpuart2 ostimer0" --example ostimer_alarm
202 Finished `dev` profile [optimized + debuginfo] target(s) in 0.02s
203 Running `/home/smw016108/Downloads/nxp/rust/uart/embassy-mcxa276/./run.sh target/thumbv8m.main-none-eabihf/debug/examples/ostimer_alarm`
2040x20002040 in core::panicking::panic_const::panic_const_mul_overflow () at library/core/src/panicking.rs:175
205warning: 175 library/core/src/panicking.rs: No such file or directory
206Supported Commands:
207
208 info - print session information
209 reset - reset target
210 reset halt - reset target and halt afterwards
211
212Loading section .vector_table, size 0x224 lma 0x20000000
213Loading section .text, size 0x2226 lma 0x20000224
214Loading section .Reset, size 0x58 lma 0x2000244c
215Loading section .rodata, size 0x6dc lma 0x200024a4
216Start address 0x2000244c, load size 11134
217Transfer rate: 16 KB/sec, 1855 bytes/write.
218```
219
220I can see in the console
221
222```console
223OSTIMER Alarm Example
224Scheduling alarm for 2 seconds...
225Alarm scheduled successfully
226Alarm expired! Callback executed.
227Scheduling another alarm for 3 seconds...
228Alarm scheduled. Waiting 1 second then canceling...
229Alarm canceled
230Alarm was successfully canceled
231Example complete
232```
233
234then I press CTRL+C to stop running
235
236```console
237^C
238Program received signal SIGINT, Interrupt.
2390x20000e64 in embassy_executor::arch::thread::Executor::run<ostimer_alarm::__cortex_m_rt_main::{closure_env#0}> (self=0x200027e8, init=...) at /home/smw016108/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/embassy-executor-0.9.1/src/arch/cortex_m.rs:106
240106 asm!("wfe");
241[Inferior 1 (process 1) detached]
242Program loaded and started (no reset)
243smw016108@smw016108:~/Downloads/nxp/rust/uart/embassy-mcxa276$
244```
245
246### Windows: Running examples (RAM, no RTT/defmt)
247
248Important: On Windows, do not use `cargo run` because `.cargo/config.toml` sets a Linux-only runner (`./run.sh`). Instead, use `probe-rs run` directly.
249
2501) Find your probe and COM port
251- List probes:
252
253 ```console
254 probe-rs list
255 ```
256- If multiple probes are attached, set the specific one (replace with your ID):
257
258 ```console
259 $env:PROBE_RS_PROBE = "1366:0101:000600110607"
260 ```
261
262- Check Windows Device Manager → Ports (COM & LPT) for the board’s COM port.
263
2642) Build the example
265
266```console
267cargo build --example hello --features "lpuart2"
268```
269
2703) Run from RAM with probe-rs
271
272```console
273probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/hello
274```
275You will see a short probe-rs warning like "unknown variant, try to set watch point"; it’s harmless.
276
2774) View output in Tera Term
278- Open Tera Term, select the board’s COMx port, 115200 8N1
279- Expected behavior per example:
280 - hello: prints a banner; simple UART output
281 - lpuart_polling / lpuart_buffered / uart_interrupt: echo typed characters
282 - adc_polling: prints ADC values periodically (ADC1 channel A8 on P1_10)
283 - adc_interrupt: prints "*** ADC interrupt TRIGGERED! ***" upon conversion completion
284 - blink: LED on PIO3_18 blinks "SOS" pattern
285 - rtc_alarm: schedules, cancels and reports alarm events on UART
286
287Notes
288- All examples run from RAM (not flashed). Reset clears the program.
289- If the first attempt after a reset fails to connect, just run the command again.
290- UART2 pins: TX=P2_2, RX=P2_3 (ALT3), 115200 8N1.
291
292Quick commands for other examples:
293
294```console
295# Build
296cargo build --example blink --features "gpio ostimer0"
297cargo build --example lpuart_polling --features "lpuart2 ostimer0"
298cargo build --example lpuart_buffered --features "lpuart2 ostimer0"
299cargo build --example uart_interrupt --features "lpuart2 ostimer0"
300cargo build --example rtc_alarm --features "lpuart2 rtc0"
301cargo build --example adc_polling --features "adc1 lpuart2"
302cargo build --example adc_interrupt --features "adc1 lpuart2"
303
304# Run (RAM)
305probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/blink
306probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/lpuart_polling
307probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/lpuart_buffered
308probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/uart_interrupt
309probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/rtc_alarm
310probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/adc_polling
311probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/adc_interrupt
312probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/ostimer_alarm
313probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/ostimer_async
314probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/ostimer_counter
315probe-rs run --chip MCXA276 --protocol swd --speed 1000 target/thumbv8m.main-none-eabihf/debug/examples/ostimer_race_test
316```
317
318How I tested on Windows
319- Windows 11; Rust stable; probe-rs 0.29.x
320- Built each example as above; ran with `probe-rs run` (RAM execution)
321- Observed UART output in Tera Term at 115200 8N1; all examples behaved as expected
322- No RTT/defmt used; purely UART or LED observation
323
324### Build Only
325
326To build without running:
327
328```console
329cargo build --features "gpio ostimer0" --example blink
330cargo build --features "lpuart2 ostimer0" --example hello
331cargo build --features "lpuart2 ostimer0" --example ostimer_alarm
332cargo build --features "lpuart2 rtc0" --example rtc_alarm
333# etc.
334```
335
336## Development Notes
337
338### Critical Fix: MCXA276 Interrupt Vector Table
339
340
341Update (SVD 25.06.00, mcxa-pac a9dd33): No manual PAC edits are required anymore. OS_EVENT and WAKETIMER0 are present and the vector table is correct. The section below is kept for historical context.
342**Problem:** The OSTIMER examples crashed during interrupt handling with a hardfault (SP=0x00000000). Investigation revealed the OS_EVENT interrupt vector was NULL in the vector table, causing the CPU to jump to address 0 when OSTIMER interrupts fired.
343
344**Root Cause:** The `mcxa276-pac/src/lib.rs` file (generated from the SVD file) was missing the `WAKETIMER0` interrupt handler declaration. This caused the `__INTERRUPTS` array to have an off-by-one error, placing OS_EVENT at IRQ 58 instead of the correct IRQ 57 position.
345
346**Solution:** Manually edited `mcxa276-pac/src/lib.rs` to add the missing WAKETIMER0 interrupt:
347
3481. Added `fn WAKETIMER0()` to the `extern "C"` block
3492. Fixed the `__INTERRUPTS: [Vector; 122]` array sequence:
350 - Changed from: `LPTMR0, _reserved, _reserved, OS_EVENT, _reserved, UTICK0, ...`
351 - Changed to: `LPTMR0, _reserved, OS_EVENT, WAKETIMER0, UTICK0, WWDT0, _reserved, ADC0, ...`
3523. Added `WAKETIMER0 = 58` to the `Interrupt` enum
353
354**Verification:** Binary analysis confirmed OS_EVENT is now at the correct position:
355- IRQ 57 = word 73 = offset 0x124 in vector table
356- OS_EVENT handler: 0x20000BB1 (verified with `arm-none-eabi-objdump`)
357
358**Note:** This is likely an issue with the NXP MCXA276.svd file or svd2rust generation. The WAKETIMER0 peripheral exists in the PAC but the interrupt handler was missing. Future regeneration of the PAC from SVD may require reapplying this fix.
359
360### Warning: Avoid `#[inline(always)]` in Performance-Critical Code
361
362Using `#[inline(always)]` can cause the Rust compiler to generate incorrect assembly, leading to register corruption or unexpected behavior. For example, in tight polling loops like those in the OSTIMER driver, this attribute may result in invalid instructions that zero registers (e.g., `movs r1, r0` causing r1=0), triggering hardfaults.
363
364## License 11## License
365 12
366This project is licensed under MIT OR Apache-2.0. 13This project is licensed under MIT OR Apache-2.0.