Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified benches/gust/drivers/adc-thin/adc-thin-cm3.o
Binary file not shown.
27 changes: 18 additions & 9 deletions benches/gust/drivers/adc-thin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,23 +261,29 @@ fn wr(a: u32, v: u32) {
/// Configure the ADC at `base` for a single-channel single conversion: sample time
/// (SMPRx picked by channel), regular sequence (SQR3 channel, SQR1 length 1), and
/// power on with CONT=0 (single-shot — never free-run). Table-free: every value is
/// bit arithmetic.
/// bit arithmetic. `cr2_extra` = caller-supplied CR2 bits OR'd into the managed
/// CR2 write (e.g. `TSVREFE` (1<<23) to read F1 internal channels Vrefint/temp; also
/// ALIGN, EXTTRIG). The managed bits (ADON, CONT=0) stay authoritative — gale#216.
#[no_mangle]
pub extern "C" fn adc_configure(base: u32, channel: u32, sample_code: u32) {
pub extern "C" fn adc_configure(base: u32, channel: u32, sample_code: u32, cr2_extra: u32) {
wr(base + smpr_reg(channel), smpr_bits(channel, sample_code));
wr(base + SQR3, sqr3_channel(channel));
wr(base + SQR1, sqr1_length(1));
// ADON on, CONT off: exactly one conversion per SWSTART.
wr(base + CR2, CR2_ADON);
// ADON on, CONT off: exactly one conversion per SWSTART. cr2_extra ORs in
// caller-supplied CR2 bits (e.g. TSVREFE) without touching the managed bits.
wr(base + CR2, CR2_ADON | cr2_extra);
}

/// Power on + select `channel`: Off → Ready. Returns the packed Ready state or
/// `ADC_FAULT` (bad channel / wrong phase). Sets CR2.ADON.
/// `ADC_FAULT` (bad channel / wrong phase). Sets CR2.ADON. `cr2_extra` = caller-
/// supplied CR2 bits OR'd into the managed write (e.g. `TSVREFE` (1<<23) to read F1
/// internal channels Vrefint/temp; also ALIGN, EXTTRIG). The managed bits (ADON,
/// CONT=0) stay authoritative — gale#216.
#[no_mangle]
pub extern "C" fn adc_enable(base: u32, state: u32, channel: u32) -> u32 {
pub extern "C" fn adc_enable(base: u32, state: u32, channel: u32, cr2_extra: u32) -> u32 {
match enable(unpack(state), channel) {
Ok(next) => {
wr(base + CR2, CR2_ADON);
wr(base + CR2, CR2_ADON | cr2_extra);
pack(next)
}
Err(_) => ADC_FAULT,
Expand All @@ -286,11 +292,14 @@ pub extern "C" fn adc_enable(base: u32, state: u32, channel: u32) -> u32 {

/// Start one conversion (SWSTART): Ready → Converting. Returns the packed Converting
/// state or `ADC_FAULT` if not Ready. Sets CR2.SWSTART (keeps ADON, CONT stays 0).
/// `cr2_extra` = caller-supplied CR2 bits OR'd into the managed write (e.g.
/// `TSVREFE` (1<<23) to read F1 internal channels Vrefint/temp; also ALIGN,
/// EXTTRIG). The managed bits (ADON, SWSTART, CONT=0) stay authoritative — gale#216.
#[no_mangle]
pub extern "C" fn adc_start(base: u32, state: u32) -> u32 {
pub extern "C" fn adc_start(base: u32, state: u32, cr2_extra: u32) -> u32 {
match begin(unpack(state)) {
Ok(next) => {
wr(base + CR2, CR2_ADON | CR2_SWSTART);
wr(base + CR2, CR2_ADON | CR2_SWSTART | cr2_extra);
pack(next)
}
Err(_) => ADC_FAULT,
Expand Down
16 changes: 8 additions & 8 deletions benches/gust/src/bin/gust_adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ pub extern "C" fn mmio_write32(addr: u32, val: u32) {
}

extern "C" {
fn adc_configure(base: u32, channel: u32, sample_code: u32);
fn adc_enable(base: u32, state: u32, channel: u32) -> u32;
fn adc_start(base: u32, state: u32) -> u32;
fn adc_configure(base: u32, channel: u32, sample_code: u32, cr2_extra: u32);
fn adc_enable(base: u32, state: u32, channel: u32, cr2_extra: u32) -> u32;
fn adc_start(base: u32, state: u32, cr2_extra: u32) -> u32;
fn adc_poll(base: u32, state: u32) -> u32;
fn adc_read(base: u32, state: u32) -> u32;
fn adc_sample(state: u32) -> u32;
Expand Down Expand Up @@ -99,7 +99,7 @@ fn main() -> ! {

// 0) channel bounds: enable with a channel above MAX_CHANNEL is rejected, no
// CR2 write.
let bad = adc_enable(ADC1, 0, MAX_CHANNEL + 1);
let bad = adc_enable(ADC1, 0, MAX_CHANNEL + 1, 0);
let cr2_bad = read_volatile((ADC1 + CR2) as *const u32);
tx(if bad == ADC_FAULT && cr2_bad == 0 {
b"adc-chanbound-ok\n"
Expand All @@ -108,7 +108,7 @@ fn main() -> ! {
});

// 1) enable: Off → Ready, the DRIVER writes CR2=ADON.
let s1 = adc_enable(ADC1, 0, CH);
let s1 = adc_enable(ADC1, 0, CH, 0);
let cr2_1 = read_volatile((ADC1 + CR2) as *const u32);
tx(if s1 != ADC_FAULT && phase_of(s1) == PH_READY && cr2_1 == CR2_ADON {
b"adc-enable-ok\n"
Expand All @@ -118,7 +118,7 @@ fn main() -> ! {

// 2) configure: table-free SMPR2/SQR3/SQR1 land exactly.
// smpr_bits(3,4)=4<<9=0x800; SQR3 SQ1=3; SQR1 length(1)=0; CR2=ADON.
adc_configure(ADC1, CH, SAMPLE_CODE);
adc_configure(ADC1, CH, SAMPLE_CODE, 0);
let smpr2 = read_volatile((ADC1 + SMPR2) as *const u32);
let sqr3 = read_volatile((ADC1 + SQR3) as *const u32);
let sqr1 = read_volatile((ADC1 + SQR1) as *const u32);
Expand All @@ -130,7 +130,7 @@ fn main() -> ! {
});

// 3) start: Ready → Converting, the DRIVER writes CR2=ADON|SWSTART.
let s3 = adc_start(ADC1, s1);
let s3 = adc_start(ADC1, s1, 0);
let cr2_3 = read_volatile((ADC1 + CR2) as *const u32);
tx(if s3 != ADC_FAULT && phase_of(s3) == PH_CONVERTING && cr2_3 == (CR2_ADON | CR2_SWSTART) {
b"adc-start-ok\n"
Expand Down Expand Up @@ -172,7 +172,7 @@ fn main() -> ! {
// 7) single-shot: the read landed Ready (not Converting); reading again is
// rejected and re-converting needs an explicit start.
let twice = adc_read(ADC1, s6);
let rearm = adc_start(ADC1, s6);
let rearm = adc_start(ADC1, s6, 0);
tx(if twice == ADC_FAULT && rearm != ADC_FAULT && phase_of(rearm) == PH_CONVERTING {
b"adc-single-shot-ok\n"
} else {
Expand Down
16 changes: 8 additions & 8 deletions benches/gust/src/bin/gust_adc_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ pub extern "C" fn mmio_write32(addr: u32, val: u32) {
}

extern "C" {
fn adc_configure(base: u32, channel: u32, sample_code: u32);
fn adc_enable(base: u32, state: u32, channel: u32) -> u32;
fn adc_start(base: u32, state: u32) -> u32;
fn adc_configure(base: u32, channel: u32, sample_code: u32, cr2_extra: u32);
fn adc_enable(base: u32, state: u32, channel: u32, cr2_extra: u32) -> u32;
fn adc_start(base: u32, state: u32, cr2_extra: u32) -> u32;
fn adc_poll(base: u32, state: u32) -> u32;
fn adc_read(base: u32, state: u32) -> u32;
fn adc_sample(state: u32) -> u32;
Expand Down Expand Up @@ -88,7 +88,7 @@ fn main() -> ! {
// 0) channel bounds: enable with a channel above MAX_CHANNEL (18) MUST be rejected
// — ADC_FAULT, no CR2 write. A dissolve that silently no-ops the bound check
// would latch an out-of-range mux input.
let bad = unsafe { adc_enable(base, 0, MAX_CHANNEL + 1) };
let bad = unsafe { adc_enable(base, 0, MAX_CHANNEL + 1, 0) };
let cr2_after_bad = rw(CR2);
if bad != ADC_FAULT || cr2_after_bad != 0 {
hprintln!("adc-chanbound FAIL: enable(18)={:#x} CR2={:#x}", bad, cr2_after_bad);
Expand All @@ -98,7 +98,7 @@ fn main() -> ! {
}

// 1) enable: Off(state=0) → Ready, driver WRITES CR2=ADON (a no-op leaves it 0).
let s1 = unsafe { adc_enable(base, 0, CH) };
let s1 = unsafe { adc_enable(base, 0, CH, 0) };
let cr2_1 = rw(CR2);
if s1 == ADC_FAULT || phase_of(s1) != PH_READY || cr2_1 != CR2_ADON {
hprintln!("adc-enable FAIL: s1={:#x} phase={} CR2={:#x}", s1, phase_of(s1), cr2_1);
Expand All @@ -110,7 +110,7 @@ fn main() -> ! {
// 2) configure: table-free bit arithmetic lands in SMPR2/SQR3/SQR1 exactly.
// smpr_bits(3,4) = 4 << ((3%10)*3) = 4 << 9 = 0x800 in SMPR2; SQR3 SQ1 = 3;
// SQR1 length(1) = 0; CR2 = ADON (single-shot, CONT=0).
unsafe { adc_configure(base, CH, SAMPLE_CODE) };
unsafe { adc_configure(base, CH, SAMPLE_CODE, 0) };
let smpr2 = rw(SMPR2);
let sqr3 = rw(SQR3);
let sqr1 = rw(SQR1);
Expand All @@ -126,7 +126,7 @@ fn main() -> ! {
}

// 3) start: Ready → Converting, driver WRITES CR2=ADON|SWSTART (keeps CONT=0).
let s3 = unsafe { adc_start(base, s1) };
let s3 = unsafe { adc_start(base, s1, 0) };
let cr2_3 = rw(CR2);
if s3 == ADC_FAULT || phase_of(s3) != PH_CONVERTING || cr2_3 != (CR2_ADON | CR2_SWSTART) {
hprintln!("adc-start FAIL: s3={:#x} phase={} CR2={:#x}", s3, phase_of(s3), cr2_3);
Expand Down Expand Up @@ -175,7 +175,7 @@ fn main() -> ! {
// free-runs. Reading AGAIN from Ready is rejected (exactly-once), and the only
// way back to Converting is an explicit start — not an implicit re-arm.
let twice = unsafe { adc_read(base, s6) };
let rearm = unsafe { adc_start(base, s6) };
let rearm = unsafe { adc_start(base, s6, 0) };
if twice != ADC_FAULT || rearm == ADC_FAULT || phase_of(rearm) != PH_CONVERTING {
hprintln!("adc-single-shot FAIL: read-twice={:#x} restart={:#x} phase={}", twice, rearm, phase_of(rearm));
ok = false;
Expand Down
Loading