aboutsummaryrefslogtreecommitdiff
path: root/amforth-6.5/avr8/words/store-i_big.asm
blob: 422da394c488b90f0eba45fd7a2aa63535e27a55 (plain)
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
; ( n addr -- ) Memory
; R( -- )
; writes a cell in flash
VE_DO_STOREI_BIG:
    .dw $ff04
    .db "(i!)"
    .dw VE_HEAD
    .set VE_HEAD = VE_DO_STOREI_BIG
XT_DO_STOREI:
    .dw PFA_DO_STOREI_BIG
PFA_DO_STOREI_BIG:
  movw temp2, tosl ; save the (word) address
  loadtos          ; get the new value for the flash cell
  push xl
  push xh
  push yl
  push yh
  ldi zl, byte3(DO_STOREI_atmega)
  out_ rampz, zl
  ldi zh, byte2(DO_STOREI_atmega)
  ldi zl, byte1(DO_STOREI_atmega)
  eicall 
  pop yh
  pop yl
  pop xh
  pop xl
  ; finally clear the stack
  loadtos
  jmp_ DO_NEXT

;
.set _pc = pc
.org NRWW_START_ADDR
DO_STOREI_atmega:
  ; write data to temp page buffer
  ; use the values in tosl/tosh at the
  ; appropiate place
  rcall pageload

  ; erase page if needed
  ; it is needed if a bit goes from 0 to 1
  com temp4
  com temp5
  and tosl, temp4
  and tosh, temp5
  or tosh, tosl
  breq DO_STOREI_writepage 

    movw zl, temp2
    ldi temp0,(1<<PGERS|1<<SPMEN)
    rcall dospm

DO_STOREI_writepage:
  ; write page
  movw zl, temp2
  ldi temp0,(1<<PGWRT|1<<SPMEN)
  rcall dospm

  ; reenable RWW section
  movw zl, temp2
  ldi temp0,(1<<RWWSRE|1<<SPMEN)
  rcall dospm
  ret

; load the desired page
.equ pagemask = ~ ( PAGESIZE - 1 )
pageload:
  movw zl, temp2
  ; get the beginning of page
  andi zl,low(pagemask)
  andi zh,high(pagemask)
  movw y, z
  ; loop counter (in words)
  ldi xl,low(pagesize)
  ldi xh,high(pagesize)
pageload_loop:
  ; we need the current flash value anyways
  movw z, y
  readflashcell temp6, temp7 ; destroys Z
  ; now check: if Z points to the same cell as temp2/3, we want the new data
  movw z, y
  cp zl, temp2
  cpc zh, temp3
  breq pageload_newdata
    movw r0, temp6
    rjmp pageload_cont
pageload_newdata:
    movw temp4, temp6
    movw r0, tosl
pageload_cont:
  ldi temp0,(1<<SPMEN)
  rcall dospm
  adiw y, 1
  sbiw x, 1
  brne pageload_loop

pageload_done:
  ret


;; dospm
;;
;; execute spm instruction
;;   temp0 holds the value for SPMCR

dospm:
  ; store status register
  in temp1,SREG
  push temp1
  cli
Wait_ee:
  sbic EECR, EEPE
  rjmp Wait_ee
wait_spm:
  in   temp1, SPMCSR
  sbrc temp1, SPMEN
  rjmp Wait_spm

  ; turn the word addres into a byte address
  writeflashcell
  ; execute spm
  out SPMCSR,temp0
  spm
  pop temp1
  ; restore status register
  out SREG,temp1
  ret

.org _pc