-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathchat-usb-host.mu4
105 lines (82 loc) · 3.63 KB
/
chat-usb-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
| This file is part of muforth: https://muforth.dev/
|
| Copyright 2002-2025 David Frech. (Read the LICENSE for details.)
| A "chat-like" driver for talking to the USB byteloader. Unfortunately,
| the approach I had to take with USB is sufficiently different that this
| is nothing like the chat, BDM, or 908 monitor "chat" drivers. Hopefully I
| can make this square peg fit ok!
loading S08 USB chat (host)
hex
| We need a different approach when programming flash via USB. For one
| thing, it's very difficult to create an on-stack buffer for the bytes to
| be programmed. On the other hand, the bytes to program are sitting in the
| USB packet buffer ... why not just read and program them from there?
|
| The idea is that we create a "hook" in the loop that processes OUT
| tokens. Normally, for each byte pulled out of the buffer, it will simply
| execute "sta 0,x", but when we are programming flash, we want to execute
| a "program byte" routine. The OUT loop calls "write-byte" - which either
| points to "sta 0,x rts" or the flash routine. It's pretty simple, really.
|
| The routine to program a byte or run an erase command follows. One
| difference with the previous code is that it is not compiled into RAM
| space. Rather, it is compiled into the "high register" space, which is
| normally never copied over to the target. This way we can copy it over as
| needed, and it isn't always taking up space in RAM. (It will generally
| alternate with the routine to execute a piece of code, setting the
| registers to known values beforehand, and returning their values
| afterwards.)
: usb ( bmRequest bRequest wValue wIndex wLength 'buffer)
usb-target usb-control drop ;
( Commands)
: u.ReadChunk ( buf a u) rot 2push
0c0 00 rot 0 2pop usb ;
: u.WriteChunk ( buf a u) rot 2push
40 01 rot 0 2pop usb ;
: u.FlashWrite ( buf a u cmd) push rot pop -rot 2push 2push
40 01 2pop 2pop usb ;
: ux.Run 40 02 0 0 0 0 usb ;
| Useful for finishing ReadSp and GetVersionAddr.
: u.read-word ( bmReq bReq - w)
0 0 2 pad usb pad beh@ ;
: u.ReadSp ( - sp)
0c0 03 u.read-word ;
: u.GetVersionAddr ( - a)
0c0 04 u.read-word ;
| If we are using the S08 to talk to some other target - perhaps
| programming a PIC or AVR - don't load anything other than what we need to
| fire up the usb-<task> command loop.
.ifndef via-s08
( XXX Are these only used in u.FlashChunk?)
: usb-c@ ( addr - byte) 1 pad u.ReadChunk pad c@ ;
: usb-c! ( byte addr) swap pad c! 1 pad u.WriteChunk ;
: u.FlashChunk ( target-addr length buffer cmd - status)
30 \eq FSTAT usb-c! ( clear flash errors)
u.FlashWrite
\eq FSTAT usb-c@ ( return status) ;
( Order of regs in memory: H CC A X PC)
: ux.Status ( - dp pc)
u.ReadSp pad swap 6 u.ReadChunk
pad c@ ( H) pad 3 + c@ ( X) hilo>
pad 4 + beh@ ;
: u.Hello ( in-ram? chunk-size)
u.GetVersionAddr
?if
pad swap 4 u.ReadChunk ( read version commit) pad bew@ ( big-endian!)
cr ." Chat firmware version "
radix preserve hex sep preserve -sep <# 4# 4# #> type
then
ux.Status nip ( pc) [ @ram #ram + #] u< dup if ." (running in RAM)" then
( Copy flash routine to RAM.) copy-flash-routine #256 ;
: u.Status ( - dp) ux.Status drop ;
: u.Run ( pc dp)
u.ReadSp ( uses pad) -rot
>lohi pad c! ( H) pad 3 + c!+ ( X) beh! ( PC)
pad swap 6 u.WriteChunk ux.Run ;
.ifdef usb-debug-via-serial
: chat-usb ( to distinguish between the usb and serial versions)
.else
: chat
.then
chat-via u.Hello u.Status u.Run u.ReadChunk u.WriteChunk u.FlashChunk ;
.then ( ndef via-s08)