Prompt Details
Model
(claude-5-5-sonnet)
Token size
942
Example input
[Insert MCU & Core Architecture]: ATmega328P (8-bit AVR RISC)
[Insert Compiler & Flags]: avr-gcc -Os
[Insert Peripherals & Clocks]: 16MHz External Crystal, Timer1 (CTC Mode, 1Hz), ADC (Interrupt), TWI/I2C
[Insert C Code Here]: #include <avr/io.h> #include <avr/interrupt.h> uint16_t adc_millivolts = 0; uint8_t sample_ready = 0; void init_hardware(void) { TCCR1B = (1 << WGM12); OCR1A = 15625; TCCR1B = (1 << CS12) | (1 << CS10); TIMSK1 = (1 << OCIE1A); ADMUX = (1 << REFS0); ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS0); sei(); } ISR(TIMER1_COMPA_vect) { ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)); } ISR(ADC_vect) { uint8_t high = ADCH; uint8_t low = ADCL; adc_millivolts = ((high << 8) | low) * (5000 / 1024); sample_ready = 1; } int main(void) { init_hardware(); while (1) { if (sample_ready) { if (adc_millivolts < 3300) PORTB |= (1 << PB5); sample_ready = 0; } } }
Example output
### 1. Hardware & Concurrency Audit Matrix
| Severity | Location/Symbol | Vulnerability Category | Root-Cause Analysis | Remediation Strategy |
| :--- | :--- | :--- | :--- | :--- |
| Critical | `adc_millivolts`, `sample_ready` | Missing `volatile` / `-Os` Register Caching | Under `avr-gcc -Os`, the compiler caches these in CPU registers (`r24`/`r25`), optimizing `if (sample_ready)` into an infinite dead loop. | Declare both shared variables as `volatile` to enforce SRAM `LDS`/`STS` instructions. |
| Critical | `ISR(ADC_vect)` (`ADCH` read first) | Hardware Register Lockup | Reading `ADCH` first leaves the ADC data register locked. | Read the 16-bit `ADC` pseudo-register directly (avr-gcc guarantees correct `ADCL` then `ADCH` order). |
| Critical | `adc_millivolts < 3300` | Non-Atomic Access / Data Tearing | Accessing a 16-bit `uint16_t` on an 8-bit core requires two loads. If `ADC_vect` fires mid-read, `main()` gets a corrupted hybrid value. | Encapsulate 16-bit shared reads within `ATOMIC_BLOCK(ATOMIC_RESTORESTATE)`. |
| Major | `TCCR1B = (1 << CS12)...` | Destructive Register Overwrite | Direct assignment (`=`) clears the `WGM12` bit set previously, reverting Timer1 to Normal mode. | Use bitwise OR (`|=`) to preserve `WGM12`. |
| Major | `ADCSRA` (`ADPS0`) | Peripheral Clock Out-of-Spec | Prescaler 2 at 16MHz drives ADC clock at 8MHz, violating the 50kHz-200kHz datasheet limit. | Set prescaler to 128 (`ADPS2 \| ADPS1 \| ADPS0`) for 125kHz. |
| Major | `while (ADCSRA & ...)` | Blocking Polling in ISR | Polling inside `TIMER1_COMPA_vect` blocks global interrupts for 13 ADC cycles, starving TWI/I2C. | Remove blocking loop; let Timer1 trigger `ADSC` and exit. |
### 2. Refactored Production Firmware
```c
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <stdint.h>
static volatile uint16_t adc_millivolts = 0U;
static volatile uint8_t sample_ready = 0U;
void init_hardware(void) {
cli();
DDRB |= (1U << DDB5);
PORTB &= ~(1U << PORTB5);
TCCR1A = 0x00U;
TCCR1B = (1U << WGM12) | (1U << CS12) | (1U << CS10);
TCNT1 = 0U;
OCR1A = 15624U;
TIFR1 = (1U << OCF1A);
TIMSK1 = (1U << OCIE1A);
ADMUX = (1U << REFS0);
ADCSRA = (1U << ADEN) | (1U << ADIF) | (1U << ADIE) | (1U << ADPS2) | (1U << ADPS1) | (1U << ADPS0);
sei();
}
ISR(TIMER1_COMPA_vect) {
ADCSRA |= (1U << ADSC);
}
ISR(ADC_vect) {
uint16_t raw_adc = ADC;
adc_millivolts = (uint16_t)(((uint32_t)raw_adc * 5000UL) >> 10U);
sample_ready = 1U;
}
int main(void) {
init_hardware();
for (;;) {
uint16_t local_mv = 0U;
uint8_t is_ready = 0U;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
if (sample_ready != 0U) {
local_mv = adc_millivolts;
sample_ready = 0U;
is_ready = 1U;
}
}
if (is_ready != 0U) {
if (local_mv < 3300U) PORTB |= (1U << PORTB5);
else PORTB &= ~(1U << PORTB5);
}
}
}
WCET & Interrupt Latency: Removing the blocking while loop from TIMER1_COMPA_vect reduces ISR execution time from ~104 μs to <1 μs, eliminating bus starvation. Replacing / 1024U with >> 10U avoids invoking avr-gcc software division.
Compiler Optimization Impact: static restricts symbol visibility; volatile forces memory-mapped reads. The ATOMIC_BLOCK minimizes interrupt-disabled time to 6 CPU cycles.
Hardware Side-Effects: Writing 1U << ADIF and 1U << OCF1A explicitly clears residual hardware interrupt flags prior to sei().
By purchasing this prompt, you agree to our terms of service
CLAUDE-5-5-SONNET
Enterprise-grade C firmware auditor for senior embedded engineers. Analyzes bare-metal & RTOS code for non-deterministic ISR race conditions, non-atomic Read-Modify-Write hazards, DMA cache coherency, clock/prescaler math errors, and MISRA-C violations. Accounts for compiler optimization flags (-O2, -Os, -O3). Outputs a severity-ranked root-cause diagnostic matrix and production-ready, refactored C code with cycle-accurate fixes.
...more
Updated 5 days ago
