Skip to content

CRITICAL: Bus fault in FspTimer.cpp on Arduino UNO R4 WiFi when calling set_period_ms() on unopened timer #509

@gip2

Description

@gip2

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:

  1. Uses Renesas RA4M1 MCU with FSP 3.8.0
  2. Timer peripheral addresses differ from other Arduino boards
  3. The crash address 03200031 matches RA4M1 GPT peripheral region
  4. 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 state

Unrecoverable 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)

  1. Connect Arduino UNO R4 WiFi
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions