-
-
Notifications
You must be signed in to change notification settings - Fork 100
Description
Board: Arduino UNO R4 WiFi
Core Version: 1.0.0
FSP Version: 3.8.0
MCU: RA4M1 (R7FA4M1AB3CFM#AA0)
Problem:
Multiple methods in FspTimer class cause bus fault crashes on Arduino UNO R4 WiFi when called on unopened timers. The crash occurs at address 03200031 and is triggered by attempting to access invalid timer control structures.
Hardware-Specific Context
This crash specifically affects Arduino UNO R4 WiFi because:
- Uses Renesas RA4M1 MCU with FSP 3.8.0
- Timer peripheral addresses differ from other Arduino boards
- The crash address
03200031matches RA4M1 GPT peripheral region - UNO R4 WiFi has specific memory map for timers
Testing on Other Boards
- ✅ Confirmed on: Arduino UNO R4 WiFi
- ❓ Not tested on: Portenta C33, other RA4M1 boards
- ❌ Not applicable to: AVR-based Arduinos, ESP boards
Actual Crash Log:
text
Bus fault is caused by precise data access violation
The bus fault occurred address is 03200031
Registers:
R0 : 20001b28 R1 : 20000340 R2 : 00000000 R3 : 03200030
PC : 00006faa LR : 00008769
Call stack: 00006faa 00008768 00008790 000087d8 000048f8 0000add0 0000ae16 000049d2 00007f4e 00007f44
Problem Analysis from Crash Log:
Bus fault at 03200031 - Invalid memory access
R3 = 03200030 - Points near fault address, likely timer control struct
PC = 00006faa - Crash in close() or related FSP function
LR = 00008769 - Return address to caller (likely set_period_ms() or end())
Problem Root Cause:
When close() is called on an unopened timer:
Timer control structure (gpt_instance_ctrl_t/agt_instance_ctrl_t) is uninitialized or NULL
FSP driver attempts to access hardware registers through invalid pointer
System generates bus fault on invalid memory access (03200031)
Entire program crashes
Minimal Crash Reproduction:
#include <FspTimer.h>
void setup() {
FspTimer timer;
// Initialize but don't open
timer.begin(TIMER_MODE_PERIODIC, GPT_TIMER, 0, 1000.0f, 50.0f);
// ANY of these will crash:
timer.set_period_ms(500); // Crash in close()
// OR
timer.set_frequency(2000.0f); // Crash in close() via set_period_ms()
// OR
timer.end(); // Crash in close()
// OR - scope exit crashes:
} // ~FspTimer() -> end() -> close() -> BUS FAULT
void loop() {}Crash Call Stack Reconstruction:
Based on addresses, likely sequence:
text
~FspTimer() [00007f44]
-> end() [00007f4e]
-> close() [000049d2]
-> R_GPT_Close() or similar [00006faa] // CRASH HERE
Why Address 03200031?
03200030 looks like a peripheral register address (timer hardware)
Attempting to write to p_reg->GTST or similar in uninitialized timer
03200031 suggests misaligned access (odd address for 32-bit register)
Complete Affected Method Chain:
// Direct crash sources:
set_period_ms() → close() → BUS FAULT
set_period_us() → set_period_ms() → close() → BUS FAULT
set_frequency() → set_period_ms() → close() → BUS FAULT
end() → close() → BUS FAULT
~FspTimer() → end() → close() → BUS FAULT // DESTRUCTOR CRASH!
// Underlying issue:
close() {
// Assumes timer_ctrl is valid
R_GPT_Close(&timer_ctrl); // timer_ctrl invalid → BUS FAULT
}Critical Implications:
Destructor Crashes (Most Serious):
void function() {
FspTimer timer; // Stack allocation
timer.begin(...);
// Forget to open() or open() fails
} // ~FspTimer() CRASHES HERE - corrupts entire program stateUnrecoverable State:
FspTimer timer;
if (!timer.begin(...)) {
timer.end(); // CRASH while trying to clean up failed init!
}Debugging Nightmare:
Crash occurs deep in FSP driver
No clear indication it's a state management issue
Call stack shows hardware access, not user code
Proven Fix Pattern:
The library already has correct pattern in setup_overflow_irq():
bool was_opened = is_opened(); // STATE CHECK
if(was_opened) {
close(); // SAFE - timer is known to be open
}Required Fixes:
Make ALL close() calls conditional:
// In set_period_ms(), end(), etc:
if(is_opened()) {
close(); // Only if actually open
}Make close() method idempotent:
bool FspTimer::close() {
if(!is_opened()) {
return true; // Already closed
}
// Original close logic
return R_GPT_Close(&ctrl) == FSP_SUCCESS;
}Add state validation in destructor path:
FspTimer::~FspTimer() {
if(init_ok) { // Only cleanup if properly initialized
end(); // Now safe
}
}Testing with Crash Reproduction:
// This code reproduces the exact crash from logs:
void reproduce_crash() {
FspTimer timer;
// Match crash scenario
timer.begin(TIMER_MODE_PERIODIC, GPT_TIMER, 0, 1000.0f, 50.0f);
// Will crash at PC=00006faa, accessing 03200031
timer.set_period_ms(100);
// OR for destructor crash:
// Let timer go out of scope
}Steps to Reproduce (Arduino UNO R4 WiFi)
- Connect Arduino UNO R4 WiFi
- Upload minimal scetch:
cpp
#include <FspTimer.h>
void setup() {
FspTimer timer;
timer.begin(TIMER_MODE_PERIODIC, GPT_TIMER, 0, 1000.0f, 50.0f);
timer.set_period_ms(500); // CRASH HERE
}
Call Stack Analysis:
text
00006faa - R_GPT_Close or similar FSP function
00008768 - FspTimer::close()
00008790 - FspTimer::set_period_ms()
000087d8 - FspTimer::set_frequency()
000048f8 - User code calling set_frequency()
... - Rest of user call stack
Severity Assessment:
Impact: High (crashes entire program)
Frequency: High (common initialization pattern)
Debugability: Low (crashes in driver, not user code)
Fix Complexity: Low (add state checks)
Urgent Action Required:
This bug makes the timer library unusable for production code because:
Random crashes from scope exits
Impossible to safely handle initialization errors
Destructor violations break C++ object lifecycle guarantees
Suggested Labels: critical, crash, bus-fault, destructor, memory-corruption, hardware-access