-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathasmfunc.S
228 lines (175 loc) · 4.24 KB
/
asmfunc.S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
;---------------------------------------------------------------------------;
; MMC hardware controls and Flash controls (C)ChaN, 2010
;---------------------------------------------------------------------------;
; Hardware dependent macros to be modified
//sparkfun microsd
//#define DDR_CS _SFR_IO_ADDR(DDRB), 0 // MMC CS pin (DDR, PORT)
//#define PORT_CS _SFR_IO_ADDR(PORTB), 0
// i2GPS
//#define DDR_CS _SFR_IO_ADDR(DDRB), 2 // MMC CS pin (DDR, PORT)
//#define PORT_CS _SFR_IO_ADDR(PORTB), 2
// Arduino Ethernet
#define DDR_CS _SFR_IO_ADDR(DDRD), 4 // MMC CS pin (DDR, PORT)
#define PORT_CS _SFR_IO_ADDR(PORTD), 4
#define DDR_CK _SFR_IO_ADDR(DDRB), 5 // MMC SCLK pin (DDR, PORT)
#define PORT_CK _SFR_IO_ADDR(PORTB), 5
#define DDR_DI _SFR_IO_ADDR(DDRB), 3 // MMC DI pin (DDR, PORT)
#define PORT_DI _SFR_IO_ADDR(PORTB), 3
#define PIN_DO _SFR_IO_ADDR(PINB), 4 // MMC DO pin (PIN, PORT)
#define PORT_DO _SFR_IO_ADDR(PORTB), 4
#define DDR_SS _SFR_IO_ADDR(DDRB), 2 // SS pin (PIN, PORT)
#define PORT_SS _SFR_IO_ADDR(PORTB),2
;---------------------------------------------------------------------------;
.nolist
#include <avr/io.h>
.list
.text
;---------------------------------------------------------------------------;
; Initialize MMC port
;
; void init_spi (void);
.global init_spi
.func init_spi
init_spi:
sbi DDR_CS ; CS: output
sbi DDR_DI ; DI: output
sbi DDR_CK ; SCLK: output
sbi DDR_SS ; Set SS to output, Atmega is SPI master
sbi PORT_SS ; set it to high
sbi PORT_DO ; DO: pull-up
ret
.endfunc
;---------------------------------------------------------------------------;
; Delay 100 microseconds
;
; void dly_us (UINT n);
.global dly_100us
.func dly_100us
dly_100us:
ldi r24, lo8(F_CPU / 100000) /* Loop counter */
1: sbiw r30, 1 /* 10 clocks per loop */
sbiw r30, 1
sbiw r30, 1
nop
dec r24
brne 1b
ret
.endfunc
;---------------------------------------------------------------------------;
; Select MMC
;
; void select (void);
.global select
.func select
select:
rcall deselect
cbi PORT_CS
rjmp rcv_spi
.endfunc
;---------------------------------------------------------------------------;
; Deselect MMC
;
; void deselect (void);
.global deselect
.func deselect
deselect:
sbi PORT_CS
; Goto next function
.endfunc
;---------------------------------------------------------------------------;
; Receive a byte
;
; BYTE rcv_spi (void);
.global rcv_spi
.func rcv_spi
rcv_spi:
ldi r24, 0xFF ; Send 0xFF to receive data
; Goto next function
.endfunc
;---------------------------------------------------------------------------;
; Transmit a byte
;
; void xmit_spi (BYTE);
.global xmit_spi
.func xmit_spi
xmit_spi:
ldi r25, 8
1: sbrc r24, 7 ; DI = Bit to sent
sbi PORT_DI ;
sbrs r24, 7 ;
cbi PORT_DI ; /
lsl r24 ; Get DO from MMC
sbic PIN_DO ;
inc r24 ; /
sbi PORT_CK ; A positive pulse to SCLK
cbi PORT_CK ; /
dec r25 ; Repeat 8 times
brne 1b ; /
ret
.endfunc
;---------------------------------------------------------------------------
; Erase a flash page
;
; void flash_erase (DWORD flash_addr);
.global flash_erase
.func flash_erase
flash_erase:
movw ZL, r22
#if FLASHEND >= 0x10000
out _SFR_IO_ADDR(RAMPZ), r24
#endif
; Initiate erase operation
ldi r24, 0b00000011
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
; Wait for end of erase operation
1: lds r24, _SFR_MEM_ADDR(SPMCSR)
sbrc r24, 0
rjmp 1b
; Re-enable read access to the flash
ldi r24, 0b00010001
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
9: ret
.endfunc
;---------------------------------------------------------------------------
; Write a flash page
;
; void flash_write (DWORD flash_addr, const BYTE* data);
.global flash_write
.func flash_write
flash_write:
push r0
push r1
#if FLASHEND >= 0x10000
out _SFR_IO_ADDR(RAMPZ), r24
#endif
; Fill page buffer
movw ZL, r22
movw XL, r20
ldi r25, lo8(SPM_PAGESIZE/2)
1: ld r0, X+
ld r1, X+
ldi r24, 0b00000001
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
adiw ZL, 2
dec r25
brne 1b
; Initiate write operation
movw ZL, r22
ldi r24, 0b00000101
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
; Wait for end of write operation
2: lds r24, _SFR_MEM_ADDR(SPMCSR)
sbrc r24, 0
rjmp 2b
; Re-enable read access to the flash
ldi r24, 0b00010001
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
9: pop r1
pop r0
ret
.endfunc