-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathchat-serial-host.mu4
154 lines (122 loc) · 5.38 KB
/
chat-serial-host.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
| This file is part of muforth: https://muforth.dev/
|
| Copyright 2002-2025 David Frech. (Read the LICENSE for details.)
loading PIC18 Serial chat (host)
hex
| Taking inspiration from the wildly successful HC08 serial chat protocol.
|
| Responds to the following commands. NOTE: these are hex values!
|
| 00 - 0f Idle - these command bytes are ignored
|
| 10 get-version - send 4 byte commit (little endian) to host
| 11 set-prog-addr - set the program (flash) memory address pointer
| 12 set-data-addr - set the data memory address pointer
| 13 get-data-addr - get the current value of the data mem ptr
| 14 run - load PC from flash-addr
| 15 read-prog-n - read n bytes from program memory, incr pointer
| 16 read-data-n - read n bytes from data memory, incr pointer
| 17 write-data - write a byte to data memory, incr pointer
|
| These are Q-series commands for programming the flash, config, and
| eeprom.
|
| 18 set-nvm-addr - set NVMADR from prog-addr
| 19 nvm-read - execute an NVM read command, return data read
| 1a nvm-write - execute an NVM write command, return status
|
| 1b - ff Idle - these command bytes are ignored
: >b send ;
: b> recv ;
: >cmd ?spkt >b ;
: >w ( w) >hilo >b >b ; ( send word little-endian)
: w> ( - w) b> b> lohi> ; ( recv word little-endian)
: cx.idle 0 >b ;
: cx.version ( - w) 10 >cmd b> b> b> b> 0123> ;
: cx.set-prog-addr ( a) 11 >cmd >hilo >b >w ; ( send 24 bit address)
: cx.set-data-addr ( a) 12 >cmd >w ; ( send 16 bit address)
: cx.get-data-addr ( - a) 13 >cmd w> ;
: cx.run ( ) 14 >cmd ;
: cx.read-prog-n ( u) 15 >cmd >b ; ( send byte-sized count, then streaming read)
: cx.read-data-n ( u) 16 >cmd >b ; ( send byte-sized count, then streaming read)
: cx.write-data ( b) 17 >cmd >b ;
.ifndef 1xk50 ( For Q-series NVM operations.)
: cx.set-nvm-addr ( ) 18 >cmd ; ( sets NVMADR from MEMADR - aka p)
: cx.nvm-read ( cmd - data)
19 >cmd >b w> ;
: cx.nvm-write ( unlock data cmd - status)
1a >cmd >b >w >b b> ;
.then
| Longest command - nvm-write - sends 5 bytes. To resync, let's send five
| no-ops, let them transmit, _then_ throw away any input bytes.
: resync 5 for cx.idle next drain flush ;
( Hook into interact code.)
: c.hello ( - chunk-size)
#115200 bps resync
cr ." Chat firmware version "
cx.version radix preserve hex sep preserve -sep u.
/page ( return erase page size as chunk size) ;
| After executing code, target has put Z - our DP - into X so that we can
| read it back. We adjust it by one byte when reading or writing it so that
| we can think of SP as representing a full-descending stack - where DP
| points *at* the last pushed byte. But the PIC hardware implements an
| empty-descending stack, where Z points one byte *below* the last pushed
| byte.
|
| Whereever possible, we try to isolate and hide this madness.
: c.get-status ( - dp) cx.get-data-addr 1+ ;
: c.run ( pc dp) 1- cx.set-data-addr cx.set-prog-addr cx.run ;
: c.read-buf ( buf u) for b> swap c!+ next drop ;
: c.read-data ( buf a u) swap cx.set-data-addr dup cx.read-data-n c.read-buf ;
: c.read-prog ( buf a u) swap cx.set-prog-addr dup cx.read-prog-n c.read-buf ;
: c.write-data ( buf a u)
swap cx.set-data-addr for c@+ swap cx.write-data next drop ;
( space = 0 means flash/config/eeprom; 1 means data/ram/io)
: c.read-space ( buf a u space) if c.read-data ^ then c.read-prog ;
.ifndef 1xk50 ( Q-series)
: c.set-nvm-addr ( a) cx.set-prog-addr cx.set-nvm-addr ;
: c.nvm-write ( data cmd)
55 -rot cx.nvm-write 80 and ( WRERR)
if error" flash write protect error" then ;
( Only write config/ee space if bytes *differ*.)
: ?ee!+ ( b)
0 ( read) cx.nvm-read over xor if ( different)
4 ( write & incr) c.nvm-write ^ then
1 ( read & incr) cx.nvm-read 2drop ;
: c.write-eeprom ( buf a u)
swap c.set-nvm-addr for c@+ swap ?ee!+ next drop ;
: c.erase ( a) c.set-nvm-addr 0 6 ( page erase) c.nvm-write ;
| For full pages, u will be /page; for the last page, it will be the
| remainder. But we want to write a full page, even for the last page - to
| fill the rest of the buffer with ff's. So we ignore the passed u.
: c.program ( buf a u)
drop c.set-nvm-addr
[ @ram #ram + #] /page c.write-data ( write buf to chip's page buffer)
0 5 ( page write) c.nvm-write ;
.else ( 1xK50)
( XXX TODO: Ddd support for 1xk50 programming.)
: c.write-eeprom ( buf a u) 2drop drop ;
: c.erase ( a) drop ;
: c.program ( buf a u) 2drop drop ;
.then ( Q-series)
( XXX not yet implemented)
: c.app-start ;
: c.app-stop ;
: c.flash-begin ;
: c.flash-end ;
| comment %%
| chat-cmd t.hello ( - chunk-size)
| chat-cmd t.get-status ( - sp)
| chat-cmd t.run ( pc sp)
| 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) %%
: chat chat-via
c.hello c.get-status c.run c.read-space c.write-data c.write-eeprom
c.app-start c.app-stop c.flash-begin c.flash-end c.erase c.program ;