-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathinteract.mu4
180 lines (135 loc) · 5.44 KB
/
interact.mu4
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
| This file is part of muforth: https://muforth.dev/
|
| Copyright 2002-2025 David Frech. (Read the LICENSE for details.)
loading AVR interaction
variable chatting
variable chat-vector
: chat-cmd ( index - index+1) dup cells constant 1+
does> @ chat-vector @ =if + @execute ^ then 2drop
error" Not connected to a chat-capable target" ;
: chat-fail error" Chat command not implemented" ;
0
chat-cmd t.hello ( - chunk-size)
chat-cmd t.status ( - dp)
chat-cmd t.run ( pc dp)
chat-cmd t.read-space ( buf a u space)
chat-cmd t.write-data ( buf a u)
chat-cmd t.write-eeprom ( buf a u)
chat-cmd t.app-start
chat-cmd t.app-stop
chat-cmd t.flash-begin
chat-cmd t.flash-end
chat-cmd t.erase ( a)
chat-cmd t.program ( buf a u)
drop
( Choose a memory space based on current host region.)
: choose-space
h preserve
'aspace flash dup 'aspace = if drop 0 ^ then ( flash)
ram 'aspace = if 1 ^ then ( ram/data)
2 ; ( eeprom)
: t.read ( buf a u) choose-space t.read-space ;
: t.read-data ( buf a u) 1 t.read-space ;
: >image ['] read-host-image ( read from memory image) du-target ;
: >chat ['] t.read ( read from connected target) du-target ;
| Chunk size is reported by the debug interface. Always use this when
| copying RAM contents or programming the flash!
variable /chunk ( chunk size, as reported by debug interface)
256 /chunk ! | Prevents mystifying divide-by-zero errors when not chatting
: copy-chunk ( 'target len - 'target+len)
| cr ." copy-chunk " 2dup swap u. u.
2dup + push over image+ -rot t.write-data pop ;
: copy-region ( a u)
| cr ." copy-region " 2dup swap u. u.
/chunk @ /mod ( r q) swap push for /chunk @ copy-chunk next
pop =if ( rem) copy-chunk drop ^ then 2drop ;
| XXX wondering if there is any need for this. On von Neumann targets
| - like ARM, RISC-V, MSP430, and S08 - it's useful to copy over the
| RAM-resident code, both at chat connect time (via hi) and before
| executing code on the target.
|
| On Harvard targets like AVR, how useful is this?
variable ram-copied ( pointer to first un-copied byte)
: copy-ram
h preserve ram
ram-copied @ dup 0= if drop \m origin then
\m here over - copy-region
\m here ram-copied ! ;
| For reading and writing PC values on the stack. Convert a normal address
| to an "ra" - return address - by shifting right one bit and swapping
| bytes; ra's are stored big-endian on the stack!
|
| To convert back, swap bytes and shift left.
meta
: >ra ( a - ra) \m cell/ >lohi hilo> ;
: ra> ( ra - a) >lohi hilo> \m cells ;
forth
| Useful utility words for printing out register contents after executing
| code remotely. See mu/target/AVR/register-trampoline.mu4 for an example
| of a simple trampoline for executing assembler routines.
: 2sp space space ;
: 4# # # # # ;
: .h16 hex <# 4# #> type ;
: .b8 binary <# 4# char _ hold 4# #> type ;
: .w .h16 2sp ;
defer verify-quietly ( - diff)
: hi
chatting on >chat t.hello /chunk !
.ifndef noverify verify-quietly drop .then
| now __chatting is __meta __meta ; ( XXX why not do this?)
;
: chat-via pop chat-vector ! hi ;
"cafe constant stack-sentinel
| Put the D stack below the task stacks and watchdog reset count.
@ram #ram + 256 - 2 - constant dp0
| Define synonyms for reading and writing target stacks.
: stack-write t.write-data ;
: stack-read t.read-data ;
ld target/common/stacks.mu4
: run ( pc) dp@ t.run ; ( don't wait for target)
: runwait ( pc) run t.status dp! ; ( wait for target)
| Set |@ and |c@ to _some_ form of target fetch. Prefer to get bytes from
| target if we're connected. This word is useful so we can set an initial
| state for target's du and dis so that inspect won't crash when it
| runs |@ to get a default ea.
: >target chatting @ if >chat ^ then >image ;
| Define our own key bindings for memory dumping and disassembly. We'll
| default to host bindings if there isn't one in our array. This way we
| only have to define the "delta" between host and target behaviours.
128 array avr-seekeys
( Default key action is to run host key code)
host-seekeys avr-seekeys 128 cells cmove
( Support for dumping memory)
: 1dump ( a)
hex-bytes ( set field width)
>image dup .addr dup .hex-bytes
chatting @ if
-valid
>chat dup _addr dup .hex-bytes
-valid
then
drop ( a) ;
( So we can easily look at the signature embedded into the image.)
: 1dump-chars ( a)
hex-bytes
>target
dup _addr dup .chars
dup .addr dup .hex-bytes
drop ;
avr-seekeys -1 du-mode dumping >target skip+ skip- 1dump ( a - a')
avr-seekeys -1 du-mode dumping-chars >target skip+ skip- 1dump-chars ( a - a')
avr-seekeys -1 du-mode disasming >target dis+ dis- 1dis ( a - a')
avr-seekeys 'seekeys ! ( switch over to our bindings)
key: d ( a - a 0) dumping 0 ;
key: C ( a - a 0) dumping-chars 0 ; ( small c is "call")
key: i ( a - a 0) disasming 0 ;
host-seekeys 'seekeys ! ( back to host bindings)
( Interactive)
( make an alias so we can still get to host's du)
: _du du ;
: du ( a - a') dumping inspect ;
: dis ( a - a') disasming inspect ;
meta
: du du ;
: dis dis ;
forth