Skip to content

Commit f8306ea

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

6 files changed

+109
-0
lines changed

src/machine/machine_atmega.go

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

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

14+
// EEPROM on ATMega
15+
type EEPROM struct {
16+
}
17+
18+
var EEPROM0 = EEPROM{}
19+
20+
// setAddress sets the address for a given read or write into the MCUs EEARH/L register.
21+
func (e EEPROM) setAddress(addr int16) error {
22+
if addr < 0 || addr > int16(e.Size()) {
23+
return errors.New("address provided is out of bounds")
24+
}
25+
26+
avr.EEARH.Set(uint8(addr >> 8))
27+
avr.EEARL.Set(uint8(addr & 0xFF))
28+
29+
return nil
30+
}
31+
32+
// WriteAt writes len(data) bytes in the EEPROMs at the provided offset.
33+
func (e EEPROM) WriteAt(data []byte, off int64) (int, error) {
34+
written := 0
35+
for i, value := range data {
36+
if err := e.WriteByteAt(value, off+int64(i)); err != nil {
37+
return written, err
38+
}
39+
written++
40+
}
41+
return written, nil
42+
}
43+
44+
// WriteByteAt performs the logic to writes a byte into the EEPROM at the given address.
45+
func (e EEPROM) WriteByteAt(value byte, addr int64) error {
46+
for avr.EECR.HasBits(avr.EECR_EEPE) {
47+
}
48+
49+
if err := e.setAddress(int16(addr)); err != nil {
50+
return err
51+
}
52+
53+
avr.EEDR.Set(value)
54+
55+
avr.EECR.SetBits(avr.EECR_EEMPE)
56+
avr.EECR.SetBits(avr.EECR_EEPE)
57+
58+
return nil
59+
}
60+
61+
// ReadAt reads exactly len(buf) into buf at the offset. It will return the amount of bytes copied or an error if one exists.
62+
// The buffer cannot be empty, and an an error is thrown if fewer bytes are read than the size of the buffer.
63+
func (e EEPROM) ReadAt(buf []byte, off int64) (int, error) {
64+
if len(buf) == 0 {
65+
return 0, nil
66+
}
67+
68+
read := 0
69+
for i := 0; i < len(buf); i++ {
70+
val, err := e.ReadByteAt(off + int64(i))
71+
if err != nil {
72+
return read, err
73+
}
74+
75+
buf[i] = val
76+
77+
read++
78+
}
79+
80+
return len(buf), nil
81+
}
82+
83+
// ReadByteAt reads and returns the byte at the specified address. An error is returned if there is a failure to read.
84+
func (e EEPROM) ReadByteAt(addr int64) (byte, error) {
85+
for avr.EECR.HasBits(avr.EECR_EEPE) {
86+
}
87+
88+
if err := e.setAddress(int16(addr)); err != nil {
89+
return byte(0), err
90+
}
91+
92+
avr.EECR.SetBits(avr.EECR_EERE)
93+
94+
return avr.EEDR.Get(), nil
95+
}
96+
1397
// I2C on AVR.
1498
type I2C struct {
1599
}

src/machine/machine_atmega1280.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111

1212
const irq_USART0_RX = avr.IRQ_USART0_RX
1313

14+
// Size returns the size of the EEPROM for this machine.
15+
func (e EEPROM) Size() int64 {
16+
return 4096
17+
}
18+
1419
const (
1520
portA Pin = iota * 8
1621
portB

src/machine/machine_atmega1284p.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import (
1010

1111
const irq_USART0_RX = avr.IRQ_USART0_RX
1212

13+
// Size returns the size of the EEPROM for this machine.
14+
func (e EEPROM) Size() int64 {
15+
return 4096
16+
}
17+
1318
// Return the current CPU frequency in hertz.
1419
func CPUFrequency() uint32 {
1520
return 20000000

src/machine/machine_atmega2560.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ const irq_USART1_RX = avr.IRQ_USART1_RX
1313
const irq_USART2_RX = avr.IRQ_USART2_RX
1414
const irq_USART3_RX = avr.IRQ_USART3_RX
1515

16+
// Size returns the size of the EEPROM for this machine.
17+
func (e EEPROM) Size() int64 {
18+
return 4096
19+
}
20+
1621
const (
1722
portA Pin = iota * 8
1823
portB

src/machine/machine_atmega328p.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111

1212
const irq_USART0_RX = avr.IRQ_USART_RX
1313

14+
// Size returns the size of the EEPROM for this machine.
15+
func (e EEPROM) Size() int64 {
16+
return 1024
17+
}
18+
1419
// getPortMask returns the PORTx register and mask for the pin.
1520
func (p Pin) getPortMask() (*volatile.Register8, uint8) {
1621
switch {

src/machine/machine_atmega328pb.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import (
1010

1111
const irq_USART0_RX = avr.IRQ_USART0_RX
1212

13+
// Size returns the size of the EEPROM for this machine.
14+
func (e EEPROM) Size() int64 {
15+
return 1024
16+
}
17+
1318
// getPortMask returns the PORTx register and mask for the pin.
1419
func (p Pin) getPortMask() (*volatile.Register8, uint8) {
1520
switch {

0 commit comments

Comments
 (0)