Skip to content

Commit 7b06385

Browse files
committed
avr: added EEPROM support for ATmega boards
1 parent 783c6a8 commit 7b06385

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

src/machine/machine_atmega.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,121 @@ package machine
55

66
import (
77
"device/avr"
8+
"errors"
89
"runtime/interrupt"
910
"runtime/volatile"
1011
"unsafe"
1112
)
1213

14+
// Default size of the EEPROM on ATMega MCUs
15+
const eepromSize = 1024
16+
17+
// EECR bitfield values.
18+
// The constants provided by the AVR package are not correct, so these are the correct fields instead.
19+
const (
20+
eecrEERE = avr.EECR_EERE - 1
21+
eecrEEPE = avr.EECR_EEPE - 1
22+
eecrEEMPE = avr.EECR_EEMPE - 2
23+
eecrEERIE = avr.EECR_EERIE - 5
24+
eecrEEPM0 = avr.EECR_EEPM0 - 12
25+
eecrEEPM1 = avr.EECR_EEPM1 - 27
26+
)
27+
28+
// EEPROM on ATMega
29+
type EEPROM struct {
30+
}
31+
32+
// setAddress sets the address for a given read or write into the MCUs EEARH/L register.
33+
func (e *EEPROM) setAddress(addr int64) error {
34+
if addr < 0 || addr > int64(eepromSize) {
35+
return errors.New("address provided is out of bounds")
36+
}
37+
38+
avr.EEARH.Set(uint8(addr >> 8))
39+
avr.EEARL.Set(uint8(addr & 0xFF))
40+
41+
return nil
42+
}
43+
44+
// WriteAt writes len(data) bytes in the EEPROMs at the provided offset.
45+
func (e *EEPROM) WriteAt(data []byte, off int64) (int, error) {
46+
written := 0
47+
for i, value := range data {
48+
if err := e.WriteByteAt(value, off+int64(i)); err != nil {
49+
return written, err
50+
}
51+
written++
52+
}
53+
return written, nil
54+
}
55+
56+
// WriteByteAt performs the logic to writes a byte into the EEPROM at the given address.
57+
func (e *EEPROM) WriteByteAt(value byte, addr int64) error {
58+
notReady := true
59+
for notReady {
60+
// Wait for the completion of the previous write (if there is one)
61+
if !avr.EECR.HasBits(1 << eecrEEPE) {
62+
notReady = false
63+
}
64+
}
65+
66+
if err := e.setAddress(addr); err != nil {
67+
return err
68+
}
69+
70+
avr.EEDR.Set(value)
71+
72+
avr.EECR.SetBits(1 << eecrEEMPE)
73+
avr.EECR.SetBits(1 << eecrEEPE)
74+
75+
return nil
76+
}
77+
78+
// ReadAt reads exactly len(buf) into buf at the offset. It will return the amount of bytes copied or an error if one exists.
79+
// The buffer cannot be empty, and an an error is thrown if fewer bytes are read than the size of the buffer.
80+
func (e *EEPROM) ReadAt(buf []byte, off int64) (int, error) {
81+
if len(buf) == 0 {
82+
return 0, errors.New("buffer cannot be empty")
83+
}
84+
85+
size := len(buf)
86+
read := 0
87+
for i := 0; i < size; i++ {
88+
val, err := e.ReadByteAt(off + int64(i))
89+
if err != nil {
90+
return read, err
91+
}
92+
93+
buf[i] = val
94+
95+
read++
96+
}
97+
98+
if read < size {
99+
return read, errors.New("fewer bytes read than size of buffer")
100+
}
101+
102+
return read, nil
103+
}
104+
105+
// ReadByteAt reads and returns the byte at the specified address. An error is returned if there is a failure to read.
106+
func (e *EEPROM) ReadByteAt(addr int64) (byte, error) {
107+
notReady := true
108+
for notReady {
109+
if !avr.EECR.HasBits(1 << eecrEEPE) {
110+
notReady = false
111+
}
112+
}
113+
114+
if err := e.setAddress(addr); err != nil {
115+
return byte(0), err
116+
}
117+
118+
avr.EECR.SetBits(1 << eecrEERE)
119+
120+
return avr.EEDR.Get(), nil
121+
}
122+
13123
// I2C on AVR.
14124
type I2C struct {
15125
}

0 commit comments

Comments
 (0)