Skip to content

Commit

Permalink
Merge pull request #44 from pmnxis/dev/i43_eeprom_every_1m
Browse files Browse the repository at this point in the history
#43 Rewrite EEPROM artificially to avoid starving every 1 minutes
  • Loading branch information
pmnxis committed Nov 5, 2023
2 parents 5cad35d + 2999de8 commit d8d85d3
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 41 deletions.
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ fn main() -> Result<(), Error> {
.0
.strip_prefix("CARGO_FEATURE_HW_")
.unwrap()
.replace("_", "-");
.replace('_', "-");

let fingerprint = MpFingerprint {
firmware_fingerprint: FirmwareFingerprint {
Expand Down
135 changes: 96 additions & 39 deletions src/components/eeprom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,23 @@ impl From<u8> for NvMemSectionKind {
}
}

impl NvMemSectionKind {
fn next(self) -> Option<Self> {
let idx = (self as u8) + 1;

if idx >= SECTION_NUM as u8 {
None
} else {
unsafe { Some(core::mem::transmute(idx)) }
}
}

// this should be generated by macro
const fn get_last() -> Self {
Self::CardPortBackup
}
}

#[derive(Clone, Copy)]
pub struct NovellaSelector<T> {
pub section: NvMemSectionKind,
Expand Down Expand Up @@ -396,14 +413,18 @@ impl NovellaSectionControlBlock {
self.inner = (self.inner & (1 << 7)) | (robin & !(1 << 7))
}

fn force_robin(&mut self, section_info: &NvSectionInfo) -> RawNvRobin {
let ret = (section_info.slot_num - 1) & (self.inner + 1);
self.inner = ret | (1 << 7);
self.set_dirty();
ret
}

fn test_and_robin(&mut self, section_info: &NvSectionInfo) -> Option<RawNvRobin> {
if !self.is_dirty() {
None
} else {
let ret = (section_info.slot_size - 1) & (self.inner + 1);
self.inner = ret | (1 << 7);
self.set_dirty();
Some(ret)
Some(self.force_robin(section_info))
}
}
}
Expand All @@ -418,16 +439,16 @@ struct NvSectionInfo {
}

#[rustfmt::skip]
const SECTION_TABLE: [NvSectionInfo; 8] = [
NvSectionInfo{sect_start_page : 0, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 256, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 512, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 768, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 1024, slot_num : 8, slot_size : 1, real_data_size : 6 },
NvSectionInfo{sect_start_page : 1152, slot_num : 8, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 1280, slot_num : 8, slot_size : 2, real_data_size : 13 },
NvSectionInfo{sect_start_page : 1536, slot_num : 8, slot_size : 3, real_data_size : 32 },
];
const SECTION_TABLE: [NvSectionInfo; 8] = [
NvSectionInfo{sect_start_page : 0, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 256, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 512, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 768, slot_num : 16, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 1024, slot_num : 8, slot_size : 1, real_data_size : 6 },
NvSectionInfo{sect_start_page : 1152, slot_num : 8, slot_size : 1, real_data_size : 4 },
NvSectionInfo{sect_start_page : 1280, slot_num : 8, slot_size : 2, real_data_size : 13 },
NvSectionInfo{sect_start_page : 1536, slot_num : 8, slot_size : 3, real_data_size : 32 },
];

const PAGE_SIZE: usize = 16;
const PAGE_SHIFT: usize = 4;
Expand Down Expand Up @@ -640,7 +661,7 @@ impl Novella {

for page_idx in 0..slot_size {
// #[cfg(i2c_addr_bits_include_msb)]
let raw_addr = Self::get_raw_addr(sect_idx, slot_size, page_idx);
let raw_addr = Self::get_raw_addr(sect_idx, slot_idx, page_idx);

let data_address_slice = (raw_addr as EepromAddress).to_be_bytes();
let i2c_address = ROM_7B_ADDRESS | ((raw_addr >> 8) as DevSelAddress & 0x7);
Expand Down Expand Up @@ -740,7 +761,7 @@ impl Novella {
// Set eeprom data address
// #[cfg(i2c_addr_bits_include_msb)]

let raw_addr = Self::get_raw_addr(sect_idx, slot_size, page_idx);
let raw_addr = Self::get_raw_addr(sect_idx, slot_idx, page_idx);

addr_buffer.copy_from_slice(&((raw_addr & 0xFF) as u8).to_be_bytes());

Expand Down Expand Up @@ -829,7 +850,7 @@ impl Novella {
// Set eeprom data address
// #[cfg(i2c_addr_bits_include_msb)]

let raw_addr = Self::get_raw_addr(sect_idx, slot_size, page_idx);
let raw_addr = Self::get_raw_addr(sect_idx, slot_idx, page_idx);

addr_buffer.copy_from_slice(&((raw_addr & 0xFF) as u8).to_be_bytes());

Expand Down Expand Up @@ -935,7 +956,7 @@ impl Novella {
// Set eeprom data address
// #[cfg(i2c_addr_bits_include_msb)]

let raw_addr = Self::get_raw_addr(sect_idx, slot_size, page_idx);
let raw_addr = Self::get_raw_addr(sect_idx, slot_idx, page_idx);

addr_buffer.copy_from_slice(&((raw_addr & 0xFF) as u8).to_be_bytes());

Expand Down Expand Up @@ -1025,7 +1046,7 @@ impl Novella {
// Set eeprom data address
// #[cfg(i2c_addr_bits_include_msb)]

let raw_addr = Self::get_raw_addr(sect_idx, slot_size, page_idx);
let raw_addr = Self::get_raw_addr(sect_idx, slot_idx, page_idx);

addr_buffer.copy_from_slice(&((raw_addr & 0xFF) as u8).to_be_bytes());

Expand Down Expand Up @@ -1269,6 +1290,33 @@ impl Novella {
}

async fn run(&self) {
fn after_write(
result: Result<(), NovellaWriteError>,
sect_idx: usize,
cb: &mut MutexGuard<'_, ThreadModeRawMutex, NovellaModuleControlBlock>,
) {
match result {
Ok(_) => {
cb.controls[sect_idx].clr_dirty();
}
Err(NovellaWriteError::MissingEeprom) => {
cb.controls[sect_idx].clr_dirty();
defmt::error!("MissingEeprom");
}
Err(NovellaWriteError::Wearout) => {
// try next time and slot
defmt::error!("Wearout, T_T try next slot later");
}
Err(NovellaWriteError::Unknown) => {
// try next time and slot
defmt::error!("Unknown, ?_? try next slot later");
}
}
}

let mut starving_kind = NvMemSectionKind::get_last();
let mut every_2sec = 0u8;

loop {
for sect_idx in 0..SECTION_TABLE.len() {
let kind = NvMemSectionKind::from(sect_idx as u8);
Expand All @@ -1281,35 +1329,44 @@ impl Novella {
let new_uptime = self.get_uptime();

defmt::debug!(
"EEPROM write on [{:02}][{:02}], ticks : {}",
"Write EEPROM on [{:02}][{:02}], ticks : {}",
sect_idx,
next_slot,
new_uptime
);

match self
let result = self
.raw_slot_write_nonblocking(&mut cb, kind, next_slot, new_uptime)
.await
{
Ok(_) => {
cb.controls[sect_idx].clr_dirty();
}
Err(NovellaWriteError::MissingEeprom) => {
cb.controls[sect_idx].clr_dirty();
defmt::error!("MissingEeprom");
}
Err(NovellaWriteError::Wearout) => {
// try next time and slot
defmt::error!("Wearout, T_T try next slot later");
}
Err(NovellaWriteError::Unknown) => {
// try next time and slot
defmt::error!("Unknown, ?_? try next slot later");
}
}
.await;
after_write(result, sect_idx, &mut cb);
}
}

if every_2sec >= 30 {
starving_kind = starving_kind.next().unwrap_or(NvMemSectionKind::from(0));
let mut cb = self.mem_storage.lock().await;

let force_next_slot = cb.controls[starving_kind as usize]
.force_robin(&SECTION_TABLE[starving_kind as usize]);

let new_uptime = self.get_uptime();
defmt::debug!(
"Rewrite starving EEPROM on [{:02}][{:02}], ticks : {}",
starving_kind as u8,
force_next_slot,
new_uptime,
);

let result = self
.raw_slot_write_nonblocking(&mut cb, starving_kind, force_next_slot, new_uptime)
.await;
after_write(result, starving_kind as usize, &mut cb);

every_2sec = 0;
} else {
every_2sec += 1;
}

Timer::after(Duration::from_secs(2)).await;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/serial_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async fn get_tid_alt(novella: &Novella) -> [u8; TID_LEN] {
let tid = novella.lock_read(eeprom::select::TERMINAL_ID).await.normal;

for a in tid {
if !(b' ' <= a && a <= b'z') {
if !(b' '..=b'z').contains(&a) {
return ALT_TID;
}
}
Expand Down

0 comments on commit d8d85d3

Please sign in to comment.