W1C Fault Flag Handler with volatile, const, static, extern, and typedef
Title: Handle a Write‑1‑to‑Clear Fault Bit in a Memory‑Mapped Register
Level: Easy
Concepts: volatile (MMIO), const pointer parameters, static internal state, extern timebase, typedef for API clarity, simple API design
Scenario
A device exposes a status register at a memory-mapped address. Bit fault_bit indicates a fault and is W1C (write one to clear). You must implement a small API that:
- Reads the volatile status register,
- Optionally clears the fault bit using the W1C rule,
- Counts how many times the fault was seen (across calls),
- Rate-limits the clear operation to at most once every
cooldown_msusing a global tickextern long g_ms_tick, - Returns a code describing what happened.
Problem Statement
Design a function that inspects a volatile status register and, if the specified fault bit is set, may clear it according to a cooldown. The function should maintain an internal static counter of seen faults and expose it to the caller via an output pointer. Use typedef to define a small enum for return codes. extern long g_ms_tick provides milliseconds since boot.
Requirements
- Allowed types only.
- Inputs:
volatile int *reg— MMIO status register (readable/writable).int fault_bit— bit index0..30(bit31reserved).bool allow_clear— iftrue, perform W1C clear (subject to cooldown).long cooldown_ms— minimum gap between two clears (≥ 0).
- Global (provided by caller/environment):
extern long g_ms_tick;— monotonically non-decreasing time.
- Outputs:
int *out_seen_count— cumulative times a fault has been observed.
- Return code (
typedef enum):RC_NOFAULT = 0— bit not setRC_SEEN_ONLY = 1— bit was set, not cleared (cooldown/allow_clear=false)RC_CLEARED = 2— bit was set and successfully clearedRC_BAD_ARG = -1— invalid inputs (no output writes)
- Behavior:
- Read
*regonce. - If
fault_bitout of range, or pointers null, returnRC_BAD_ARG. - If fault bit is set, increment static
seen_countand attempt clear only if:allow_clear == trueandg_ms_tick - last_clear_ms ≥ cooldown_ms.
Clearing uses W1C: write back a value with onlyfault_bitset to1(other bits must be0in the write).
- Update a static
last_clear_msfor cooldown tracking. - Always write the current
seen_countto*out_seen_counton success.
- Read
Function Details
- Name:
handle_w1c_fault - Arguments:
volatile int *regint fault_bitbool allow_clearlong cooldown_msint *out_seen_count
- Return Value:
int— One ofRC_*values described above.
- Description:
Usesvolatilefor MMIO safety;constis not appropriate forregbecause we may write. Keeps internal state (seen_count,last_clear_ms) asstaticso state persists across calls. Uses anextern long g_ms_tick(declared elsewhere) for simple rate limiting.
Solution Approach
- Validate pointers and ranges.
- Compute
mask = (1 << fault_bit)usingint. - Read
val = *reg;and check(val & mask). - If not set →
RC_NOFAULT. - If set:
- Increment
static int seen_count. - If
allow_clearand cooldown satisfied, write*reg = mask;(W1C) and setlast_clear_ms = g_ms_tick; returnRC_CLEARED. - Else return
RC_SEEN_ONLY.
- Increment
- On success write
*out_seen_count = seen_count.
Tasks to Perform
- Define
typedef enum { RC_NOFAULT=0, RC_SEEN_ONLY=1, RC_CLEARED=2, RC_BAD_ARG=-1 } RetCode;. - Declare
extern long g_ms_tick;in your module (defined elsewhere). - Implement
handle_w1c_faultwith staticint seen_countand staticlong last_clear_ms. - Validate args:
reg != NULL,out_seen_count != NULL,0 ≤ fault_bit ≤ 30,cooldown_ms ≥ 0. - Perform logic per “Solution Approach”.
- Return appropriate
RetCode.
Test Cases
| # | Inputs / Precondition | Expected Output | Notes |
|---|---|---|---|
| 1 | *reg=0x00, fault_bit=3, allow_clear=true, cooldown_ms=0, g_ms_tick=0 |
ret=RC_NOFAULT, seen=0 |
No fault |
| 2 | *reg=0x08 (bit3), allow_clear=false |
ret=RC_SEEN_ONLY, seen=1, *reg unchanged |
Clear not allowed |
| 3 | *reg=0x08, allow_clear=true, cooldown_ms=0, g_ms_tick=100 |
ret=RC_CLEARED, seen=2, write *reg=0x08 |
W1C write clears bit3 |
| 4 | Fault again immediately with cooldown_ms=50, g_ms_tick=120 |
ret=RC_SEEN_ONLY, seen=3 |
Cooldown blocks clear |
| 5 | Later g_ms_tick=180 (≥ 50ms gap), bit set |
ret=RC_CLEARED, seen=4 |
Cooldown satisfied |
| 6 | reg=NULL or out_seen_count=NULL or fault_bit=31 |
ret=RC_BAD_ARG |
Invalid args |