Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
[fw/altos] / src / avr / ao_eeprom_avr.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  * Copyright © 2011  Anthony Towns <aj@erisian.com.au>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18  */
19
20 #include <ao.h>
21 #include <ao_storage.h>
22
23 /* Total bytes of available storage */
24 ao_pos_t        ao_storage_total = 1024;
25
26 /* Block size - device is erased in these units. */
27 ao_pos_t        ao_storage_block = 1024;
28
29 /* Byte offset of config block. Will be ao_storage_block bytes long */
30 ao_pos_t        ao_storage_config = 0;
31
32 /* Storage unit size - device reads and writes must be within blocks of this size. */
33 uint16_t        ao_storage_unit = 1024;
34
35 /*
36  * The internal flash chip is arranged in 8 byte sectors; the
37  * chip cannot erase in units smaller than that.
38  *
39  * Writing happens in units of 2 bytes and
40  * can only change bits from 1 to 0. So, you can rewrite
41  * the same contents, or append to an existing page easily enough
42  */
43
44 /*
45  * Erase the specified sector
46  */
47 uint8_t
48 ao_storage_erase(ao_pos_t pos) 
49 {
50         /* Not necessary */
51         return 1;
52 }
53
54 #define ao_intflash_wait_idle() do {                                    \
55                 /* Wait for any outstanding writes to complete */       \
56                 while (EECR & (1 << EEPE))                              \
57                         ;                                               \
58         } while (0)                                                     \
59
60 static void
61 ao_intflash_write(uint16_t pos, uint8_t d)
62 {
63         ao_intflash_wait_idle();
64         EEAR = pos;
65         EEDR = d;
66         ao_arch_critical(
67                 EECR |= (1 << EEMPE);
68                 EECR |= (1 << EEPE);
69                 );
70 }
71
72 static uint8_t
73 ao_intflash_read(uint16_t pos)
74 {
75         ao_intflash_wait_idle();
76         EEAR = pos;
77
78         EECR |= (1 << EERE);
79         return EEDR;
80 }
81 /*
82  * Write to flash
83  */
84
85 uint8_t
86 ao_storage_device_write(ao_pos_t pos32, void *v, uint16_t len) 
87 {
88         uint16_t pos = pos32;
89         uint8_t *d = v;
90
91         if (pos >= ao_storage_total || pos + len > ao_storage_total)
92                 return 0;
93
94         while (len--)
95                 ao_intflash_write(pos++, *d++);
96
97         return 1;
98 }
99
100 /*
101  * Read from flash
102  */
103 uint8_t
104 ao_storage_device_read(ao_pos_t pos, void *v, uint16_t len) 
105 {
106         uint8_t *d = v;
107         
108         if (pos >= ao_storage_total || pos + len > ao_storage_total)
109                 return 0;
110         while (len--)
111                 *d++ = ao_intflash_read(pos++);
112         return 1;
113 }
114
115 void
116 ao_storage_flush(void) 
117 {
118 }
119
120 void
121 ao_storage_setup(void)
122 {
123 }
124
125 void
126 ao_storage_device_info(void) 
127 {
128         printf ("Using internal flash\n");
129 }
130
131 void
132 ao_storage_device_init(void)
133 {
134 }