~ubuntu-branches/ubuntu/gutsy/avr-libc/gutsy

« back to all changes in this revision

Viewing changes to libc/misc/eeprom.S

  • Committer: Bazaar Package Importer
  • Author(s): Hakan Ardo
  • Date: 2006-05-01 12:03:39 UTC
  • mto: (3.1.1 edgy)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20060501120339-q93dxulpunby36dj
Tags: upstream-1.4.4
ImportĀ upstreamĀ versionĀ 1.4.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (c) 2002, Marek Michalkiewicz
 
2
   Copyright (c) 2005, Bjoern Haase
2
3
   All rights reserved.
3
4
 
4
5
   Redistribution and use in source and binary forms, with or without
31
32
 
32
33
   Contributors:
33
34
     Created by Marek Michalkiewicz <marekm@linux.org.pl>
34
 
     eeprom_write_word and eeprom_write_block added by Artur Lipowski <LAL@pro.onet.pl>
 
35
     eeprom_write_word and eeprom_write_block added by Artur Lipowski
 
36
     <LAL@pro.onet.pl>
 
37
     Complete rewrite using the original interface by Bjoern Haase
 
38
     <bjoern.haase@de.bosch.com>.
35
39
 */
36
40
 
37
41
#include "macros.inc"
38
42
#include "ctoasm.inc"
 
43
#include "avr/io.h"
 
44
#ifndef __EEPROM_REG_LOCATIONS__
 
45
/* 6-byte string denoting where to find the EEPROM registers in memory space.
 
46
   Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM
 
47
   subroutines.
 
48
   First two letters:  EECR address.
 
49
   Second two letters: EEDR address.
 
50
   Last two letters:   EEAR address.  */
 
51
#define __EEPROM_REG_LOCATIONS__ 1C1D1E
 
52
#endif
 
53
 
 
54
/* As long as we don't have a proper multilib environment: Let's make it
 
55
   possible to override the locations defined in the io headers.  */
 
56
#ifdef EEPROM_REG_LOCATIONS_OVERRIDE
 
57
 
 
58
#undef  __EEPROM_REG_LOCATIONS__
 
59
#define __EEPROM_REG_LOCATIONS__ EEPROM_REG_LOCATIONS_OVERRIDE
 
60
 
 
61
#define HEXNR CONCAT1(0x , EEPROM_REG_LOCATIONS_OVERRIDE)
 
62
 
 
63
#ifdef EECR
 
64
#undef EECR
 
65
#define EECR _SFR_IO8((HEXNR >> 16) & 0xFF)
 
66
#endif
 
67
 
 
68
#ifdef EEDR
 
69
#undef EEDR
 
70
#define EEDR _SFR_IO8((HEXNR >> 8) & 0xFF )
 
71
#endif
 
72
 
 
73
#ifdef EEAR
 
74
#undef EEAR
 
75
#define EEAR _SFR_IO8(HEXNR & 0xFF)
 
76
#endif
 
77
 
 
78
#ifdef EEARH
 
79
#undef EEARH
 
80
#endif
 
81
 
 
82
#ifdef EEARL
 
83
#undef EEARL
 
84
#define EEARL EEAR
 
85
#endif
 
86
 
 
87
#endif
 
88
 
 
89
#define _EELABEL(x) CONCAT1(__,CONCAT1(x, CONCAT1 (_,__EEPROM_REG_LOCATIONS__)))
39
90
 
40
91
/* the same library is used for 2313 and 8515 for now -
41
92
   I hope writing 0 to non-existent EEARH doesn't hurt... */
43
94
#define EEARH (EEARL+1)
44
95
#endif
45
96
 
46
 
#define addr_hi rP0
47
 
#define addr_lo rP1
48
 
#define res_hi rP0
49
 
#define res_lo rP1
50
97
 
51
98
#ifdef L_eeprom_read_byte
52
 
/* read one byte from EEPROM */
53
 
/* uint8_t eeprom_read_byte(const uint8_t *addr); */
54
 
/* addr = r25:r24, result = r25(=0):r24 */
55
 
 
56
 
        .section .text
57
 
        .global _U(eeprom_read_byte)
58
 
 
59
 
_U(eeprom_read_byte):
 
99
/* read one byte from EEPROM.
 
100
   addr = r26:r27, result = __tmp_reg__ 
 
101
   Post increment r26:r27.  */
 
102
 
 
103
        .section .text.eeprom, "ax", @progbits
 
104
        .global _EELABEL(eeprom_read_byte)
 
105
 
 
106
_EELABEL(eeprom_read_byte):
60
107
        sbic    _SFR_IO_ADDR(EECR), EEWE
61
 
        rjmp    _U(eeprom_read_byte)    /* make sure EEPROM is ready */
 
108
        rjmp    _EELABEL(eeprom_read_byte)      /* make sure EEPROM is ready */
62
109
#ifdef EEARH
63
 
        out     _SFR_IO_ADDR(EEARH), addr_hi
 
110
        out     _SFR_IO_ADDR(EEARH),r27
64
111
#endif
65
 
        out     _SFR_IO_ADDR(EEARL), addr_lo
 
112
        out     _SFR_IO_ADDR(EEARL),r26
66
113
        sbi     _SFR_IO_ADDR(EECR), EERE
67
 
        clr     res_hi          /* gcc wants result extended to "int"? */
68
 
        in      res_lo, _SFR_IO_ADDR(EEDR)
 
114
        adiw    r26,1 /* Increment x register */
 
115
        in      __tmp_reg__, _SFR_IO_ADDR(EEDR)
69
116
        ret
70
117
#endif /* L_eeprom_read_byte */
71
118
 
72
119
#ifdef L_eeprom_read_word
73
 
/* read a little endian 16-bit word from EEPROM */
74
 
/* uint16_t eeprom_read_word(const uint16_t *addr); */
75
 
/* addr = r25:r24, result = r25:r24 */
76
 
 
77
 
        .global _U(eeprom_read_word)
78
 
 
79
 
_U(eeprom_read_word):
80
 
        sbic    _SFR_IO_ADDR(EECR), EEWE
81
 
        rjmp    _U(eeprom_read_word)    /* make sure EEPROM is ready */
82
 
#ifdef EEARH
83
 
        out     _SFR_IO_ADDR(EEARH), addr_hi
84
 
#endif
85
 
        out     _SFR_IO_ADDR(EEARL), addr_lo
86
 
        sbi     _SFR_IO_ADDR(EECR), EERE
87
 
        adiw    addr_lo, 1
88
 
        in      __tmp_reg__, _SFR_IO_ADDR(EEDR)
89
 
#ifdef EEARH
90
 
        out     _SFR_IO_ADDR(EEARH), addr_hi
91
 
#endif
92
 
        out     _SFR_IO_ADDR(EEARL), addr_lo
93
 
        sbi     _SFR_IO_ADDR(EECR), EERE
94
 
        mov     res_lo, __tmp_reg__
95
 
        in      res_hi, _SFR_IO_ADDR(EEDR)
 
120
/* read one word from EEPROM.
 
121
   addr = r26:r27, result = r30:r31
 
122
   Post increment r26:r27.  */
 
123
 
 
124
        .section .text.eeprom, "ax", @progbits
 
125
        .global _EELABEL(eeprom_read_word)
 
126
 
 
127
_EELABEL(eeprom_read_word):
 
128
        rcall _EELABEL(eeprom_read_byte)
 
129
        mov r30,__tmp_reg__
 
130
        rcall _EELABEL(eeprom_read_byte)
 
131
        mov r31,__tmp_reg__
96
132
        ret
97
 
#endif /* L_eeprom_read_word */
98
 
 
99
 
#undef res_hi
100
 
#undef res_lo
 
133
#endif
101
134
 
102
135
#ifdef L_eeprom_write_byte
103
 
/* write a byte to EEPROM */
104
 
/* void eeprom_write_byte(uint8_t *addr, uint8_t val); */
105
 
/* addr = r25:r24, val = r22 */
106
 
#define val rP3
107
 
 
108
 
        .global _U(eeprom_write_byte)
109
 
 
110
 
_U(eeprom_write_byte):
 
136
/* write a byte to EEPROM
 
137
   Address in r26:r27, value in __tmp_reg__
 
138
   Post increment r26:r27.  */
 
139
 
 
140
        .section .text.eeprom, "ax", @progbits
 
141
        .global _EELABEL(eeprom_write_byte)
 
142
 
 
143
_EELABEL(eeprom_write_byte):
111
144
        sbic    _SFR_IO_ADDR(EECR), EEWE
112
 
        rjmp    _U(eeprom_write_byte)   /* make sure EEPROM is ready */
 
145
        rjmp    _EELABEL(eeprom_write_byte)     /* make sure EEPROM is ready */
113
146
#ifdef EEARH
114
 
        out     _SFR_IO_ADDR(EEARH), addr_hi
 
147
        out     _SFR_IO_ADDR(EEARH), r27
115
148
#endif
116
 
        out     _SFR_IO_ADDR(EEARL), addr_lo
117
 
        out     _SFR_IO_ADDR(EEDR), val
 
149
        out     _SFR_IO_ADDR(EEARL), r26
 
150
        out     _SFR_IO_ADDR(EEDR),__tmp_reg__
 
151
        adiw    r26,1 /* Increment x register */
118
152
        in      __tmp_reg__, _SFR_IO_ADDR(SREG)
119
153
        cli                     ; /* no ints between setting EEMWE and EEWE */
120
154
        sbi     _SFR_IO_ADDR(EECR), EEMWE
125
159
#endif /* L_eeprom_write_byte */
126
160
 
127
161
#ifdef L_eeprom_write_word
128
 
/* write a word to EEPROM */
129
 
/* void eeprom_write_word (uint16_t *addr, uint16_t val); */
130
 
/* addr = r25:r24, val = r23:r22 */
131
 
#define val_hi rP2
132
 
#define val_lo rP3
133
 
 
134
 
        .global _U(eeprom_write_word)
135
 
 
136
 
_U(eeprom_write_word):
137
 
        ser     rTI0                            ; set flag to indicate that
138
 
                                                ; the first (LSB) byte will be written
139
 
        in      __tmp_reg__, _SFR_IO_ADDR(SREG)
140
 
eeprom_write_word_start:
141
 
        sbic    _SFR_IO_ADDR(EECR), EEWE
142
 
        rjmp    eeprom_write_word_start         ; make sure EEPROM is ready
143
 
#ifdef EEARH
144
 
        out     _SFR_IO_ADDR(EEARH), addr_hi
 
162
/* write a word to EEPROM
 
163
   Address in r26:r27, value in __tmp_reg__ (LSB) and __zero_reg__ (MSB)
 
164
   Post increment r26:r27.  */
 
165
 
 
166
        .section .text.eeprom, "ax", @progbits
 
167
        .global _EELABEL(eeprom_write_word)
 
168
 
 
169
_EELABEL(eeprom_write_word):
 
170
        rcall _EELABEL(eeprom_write_byte)
 
171
        mov __tmp_reg__,__zero_reg__
 
172
        rcall _EELABEL(eeprom_write_byte)
 
173
        clr __zero_reg__
 
174
        ret
145
175
#endif
146
 
        out     _SFR_IO_ADDR(EEARL), addr_lo
147
 
        out     _SFR_IO_ADDR(EEDR), val_lo
148
 
        cli                                     ; no ints between setting EEMWE and EEWE
149
 
        sbi     _SFR_IO_ADDR(EECR), EEMWE
150
 
        sbi     _SFR_IO_ADDR(EECR), EEWE
151
 
        out     _SFR_IO_ADDR(SREG), __tmp_reg__
152
 
        sbrs    rTI0, 0                         ; if flag is cleared it means that
153
 
        ret                                     ; we write both bytes
154
 
                        
155
 
        subi    addr_lo, lo8(-1)                ; prepare to writie MSB
156
 
        sbci    addr_hi, hi8(-1)
157
 
        mov     val_lo, val_hi
158
 
        clr     rTI0                            ; clear flag to indicate that
159
 
        rjmp    eeprom_write_word_start         ; the second (MSB) byte will be written
160
 
        
161
 
#undef val_hi
162
 
#undef val_lo
163
 
#endif /* L_eeprom_write_word */
164
 
 
165
 
#undef addr_hi
166
 
#undef addr_lo
167
 
 
168
 
#define buf_hi rP0
169
 
#define buf_lo rP1
170
 
#define addr_hi rP2
171
 
#define addr_lo rP3
172
 
#define n_hi rP4
173
 
#define n_lo rP5
174
176
 
175
177
#ifdef L_eeprom_read_block
176
 
/* read a block of bytes from EEPROM */
177
 
/* void eeprom_read_block(void *buf, const void *addr, size_t n); */
178
 
/* buf = r25:r24, addr = r23:r22, n = r21:r20 */
179
 
 
180
 
        .global _U(eeprom_read_block)
181
 
 
182
 
_U(eeprom_read_block):
183
 
        cp      n_lo, __zero_reg__
184
 
        cpc     n_hi, __zero_reg__
185
 
        breq    eeprom_read_block_done
186
 
        LOAD_X(buf_lo, buf_hi)
187
 
eeprom_read_block_busy:
188
 
        sbic    _SFR_IO_ADDR(EECR), EEWE
189
 
        rjmp    eeprom_read_block_busy  /* make sure EEPROM is ready */
190
 
eeprom_read_block_loop:
191
 
#ifdef EEARH
192
 
        out     _SFR_IO_ADDR(EEARH), addr_hi
193
 
#endif
194
 
        out     _SFR_IO_ADDR(EEARL), addr_lo
195
 
        sbi     _SFR_IO_ADDR(EECR), EERE
196
 
        subi    addr_lo, lo8(-1)
197
 
        sbci    addr_hi, hi8(-1)
198
 
        in      __tmp_reg__, _SFR_IO_ADDR(EEDR)
199
 
        st      X+, __tmp_reg__
200
 
        subi    n_lo, lo8(1)
201
 
        sbci    n_hi, hi8(1)
202
 
        brne    eeprom_read_block_loop
203
 
eeprom_read_block_done:
 
178
/* read a block of n (maximum 256) bytes from EEPROM 
 
179
   ram_buffer = r30:r31, eeprom_addr = r26:r27, n = __zero_reg__
 
180
   an initial value of 0 in __zero_reg__ corresponds to a value of n == 256. */
 
181
 
 
182
        .section .text.eeprom, "ax", @progbits
 
183
        .global _EELABEL(eeprom_read_block)
 
184
        .global _EELABEL(eeprom_read_byte)
 
185
 
 
186
_EELABEL(eeprom_read_block):
 
187
        rcall _EELABEL(eeprom_read_byte)
 
188
        st z+,__tmp_reg__
 
189
        dec __zero_reg__
 
190
        brne _EELABEL(eeprom_read_block)
204
191
        ret
205
192
#endif /* L_eeprom_read_block */
206
193
 
207
194
#ifdef L_eeprom_write_block
208
 
/* write a block of bytes to EEPROM */
209
 
/* void eeprom_write_block (const void *buf, void *addr, size_t n); */
210
 
/* buf = r25:r24, addr = r23:r22, n = r21:r20 */
211
 
 
212
 
        .global _U(eeprom_write_block)
213
 
 
214
 
_U(eeprom_write_block):
215
 
        cp      n_lo, __zero_reg__              ; check if really there is something to write
216
 
        cpc     n_hi, __zero_reg__
217
 
        breq    eeprom_write_block_done
218
 
        LOAD_X(buf_lo, buf_hi)
219
 
        in      buf_lo, _SFR_IO_ADDR(SREG)      ; reuse buf_lo as the SREG temporary storage
220
 
eeprom_write_block_busy:
221
 
        sbic    _SFR_IO_ADDR(EECR), EEWE
222
 
        rjmp    eeprom_write_block_busy         ; make sure EEPROM is ready
223
 
#ifdef EEARH
224
 
        out     _SFR_IO_ADDR(EEARH), addr_hi
225
 
#endif
226
 
        out     _SFR_IO_ADDR(EEARL), addr_lo
227
 
        ld      __tmp_reg__, X+
228
 
        out     _SFR_IO_ADDR(EEDR), __tmp_reg__  
229
 
        cli                                     ; no ints between setting EEMWE and EEWE
230
 
        sbi     _SFR_IO_ADDR(EECR), EEMWE
231
 
        sbi     _SFR_IO_ADDR(EECR), EEWE
232
 
        out     _SFR_IO_ADDR(SREG), buf_lo
233
 
        subi    addr_lo, lo8(-1)
234
 
        sbci    addr_hi, hi8(-1)
235
 
        subi    n_lo, lo8(1)
236
 
        sbci    n_hi, hi8(1)
237
 
        brne    eeprom_write_block_busy
238
 
eeprom_write_block_done:
 
195
/* Write a block of n (maximum 256) bytes to EEPROM 
 
196
   ram_pointer = r30:r31, eeprom_addr = r26:r27, n = __zero_reg__
 
197
   an initial value of 0 in __zero_reg__ correspond to a value of n == 256. */
 
198
 
 
199
        .section .text.eeprom, "ax", @progbits
 
200
        .global _EELABEL(eeprom_write_block)
 
201
        .global _EELABEL(eeprom_write_byte)
 
202
 
 
203
_EELABEL(eeprom_write_block):
 
204
        ld __tmp_reg__,z+
 
205
        rcall _EELABEL(eeprom_write_byte)
 
206
        dec __zero_reg__
 
207
        brne _EELABEL(eeprom_write_block)
239
208
        ret
240
209
#endif /* L_eeprom_write_block */
241
210