Last active
September 12, 2022 14:09
-
-
Save fvilante/d8263588973a3cfd05074f2d3bb7efcd to your computer and use it in GitHub Desktop.
Low level function to read/write EEPROM on avr328p 8-bits microcontroler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// author: @FlavioVilante | |
// MIT License - Copyright 2022 | |
use ruduino::prelude::without_interrupts; | |
use crate::microcontroler::register:: { | |
write_register, | |
read_register, | |
}; | |
use crate::common:: { | |
word_to_byte, | |
get_bit_at, | |
}; | |
//EEPROM registers addresses and bits | |
const EEARH: *mut u8 = 0x42 as *mut u8; | |
const EEARL: *mut u8 = 0x41 as *mut u8; | |
const EECR: *mut u8 = 0x3F as *mut u8; | |
const EEDR: *mut u8 = 0x40 as *mut u8; | |
const EEPE: u8 = 0b0000010; | |
const EEMPE: u8 = 0b0000100; | |
const EERE: u8 = 0b0000001; | |
// normalize is to clamp the 16 bits address to a 9 bits address (1+8) | |
fn normalize_eeprom_address(address: u16) -> (u8, u8) { | |
let (address_low, address_high) = word_to_byte(address); | |
let bit9 = get_bit_at(address_high, 0); // only bit 9 of address16 are used, other bits are reserved by the microcontroller hardware | |
(bit9, address_low) | |
} | |
pub fn read_eeprom(address: u16) -> u8 { | |
let (bit9, address_low) = normalize_eeprom_address(address); | |
// set EEPROM address register | |
write_register(EEARH, bit9); | |
write_register(EEARL, address_low); | |
//do read | |
while (read_register(EECR) & (1<<EEPE)) == 1 { }; // wait until EEPE become to zero by hardware | |
write_register(EECR, read_register(EECR) | (1<<EERE)); | |
read_register(EEDR) | |
} | |
pub fn write_eeprom(address: u16, data: u8) -> () { | |
// set EEPROM address and data register | |
let (bit9, address_low) = normalize_eeprom_address(address); | |
write_register(EEARH, bit9); | |
write_register(EEARL, address_low); | |
write_register(EEDR, data); | |
// write operation | |
while (read_register(EECR) & (1<<EEPE)) == 1 { }; // wait until EEPE become to zero | |
without_interrupts(|| { | |
write_register(EECR, read_register(EECR) | (1<<EEMPE)); | |
write_register(EECR, read_register(EECR) | (1<<EEPE)); | |
}); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// low level functions to read and write values direct on microcontroler registers | |
// for details on what work each register perform see microcontroler datasheet | |
// for example: ATMEL AVR328P DATASHEET -> https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf | |
pub fn write_register(reg_address: *mut u8, value: u8) -> () { | |
unsafe { | |
core::ptr::write_volatile(reg_address, value); | |
} | |
} | |
pub fn read_register(reg_address: *const u8) -> u8 { | |
unsafe { | |
core::ptr::read_volatile(reg_address) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment