-
Notifications
You must be signed in to change notification settings - Fork 30
/
chat4-host.mu4
127 lines (96 loc) · 4.08 KB
/
chat4-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
| This file is part of muforth: https://muforth.dev/
|
| Copyright 2002-2024 David Frech. (Read the LICENSE for details.)
loading MSP430 serial chat protocol v4 (host)
hex
| Taking inspiration from the wildly successful HC08 serial chat protocol.
|
| Responds to the following commands. NOTE: these are hex values!
|
| 00 - 3f Idle - these command bytes are ignored
|
| 40 VersionAddr - get the address of the version commit
| 41 SetAddr - set the memory address pointer
| 42 GetStatus - get SP, PC, SR, and CP
| 43 Run - set SP, PC, SR, CP, and execute
| 44 ReadWords - read N words, incrementing by 2 as we go
| 45 WriteWord - write a word to memory, incr pointer by 2
| 46 WriteByte - write a byte to memory, incr pointer by 1
| 47 SetFlashCmd - set flash command, clear flash status
| 48 GetFlashStatus - read accumulated flash status word
| 49 FlashWord - write a word to flash, incr pointer
|
| 4a - ff Idle - these command bytes are ignored
: >b send ;
: b> recv ;
: >w >hilo >b >b ;
: w> b> b> lohi> ;
: c.Idle 0 >b ;
: c.VersionAddr ( ) 40 >b ;
: c.SetAddr ( a) 41 >b >w ;
: c.GetStatus ( - sp sr cp)
42 >b w> w> drop ( pc) w> w> ;
: c.Run ( pc sr cp)
43 >b rot >w swap >w >w ;
: c.ReadWords ( n) 44 >b >b ; ( then read streamed bytes)
: c.WriteWord ( w) 45 >b >w ;
: c.WriteByte ( b) 46 >b >b ;
: c.SetFlashCmd ( cmd) 47 >b >w ;
: c.GetFlashStatus ( - status)
48 >b w> ;
: c.FlashWord ( w) 49 >b >w ;
( Send two no-ops, let them transmit, _then_ throw away any input bytes.)
: resync c.Idle c.Idle drain flush ;
: get-version ( - n) c.VersionAddr 2 c.ReadWords w> w> ( lo hi) 10 << + ;
: c.setup-chunk ( buf a u - #words)
swap c.SetAddr swap m ! 1+ 2/ ( words) ;
: c.ReadChunk ( buf a u)
c.setup-chunk dup c.ReadWords for w> >hilo m& m& next ;
: c.WriteChunk ( buf a u)
c.setup-chunk for m* m* lohi> c.WriteWord next ;
( FRAM devices have an MPUCTL0 register)
.equates. .contains MPUCTL0 .if
: unlock-mpu
\eq MPUCTL0 c.SetAddr [ \eq MPUKEY 1+ #] c.WriteWord ;
: lock-mpu
[ \eq MPUCTL0 1+ #] c.SetAddr 0 c.WriteByte ;
: c.ErasePage ( a - fail?) ( XXX - no-op?) drop 0 ;
: c.FlashChunk ( buf a u - fail?)
unlock-mpu
\eq MPUSAM c.SetAddr 1 c.ReadWords w> 0200 or ( enable W bit for segment3)
\eq MPUSAM c.SetAddr c.WriteWord
c.WriteChunk
lock-mpu 0 ;
.then
( Flash devices have an FCTL1 register.)
.equates. .contains FCTL1 .if
: ?flash-status ( - fail?) c.GetFlashStatus 84 and ;
: c.ErasePage ( a - fail?)
[ \eq FERASE \eq FKEY + #] c.SetFlashCmd
c.SetAddr 0 c.FlashWord ?flash-status ;
: c.FlashChunk ( buf a u - fail?)
[ \eq FWRT \eq FKEY + #] c.SetFlashCmd
c.setup-chunk for m* m* lohi> c.FlashWord next ?flash-status ;
.then
| chat4 rewrites SP with the memory pointer when we execute c.Run, so we
| have to pass SP back and forth.
variable chat-sp
| Likewise, we don't really care about the status register, but chat passes
| it back and forth.
variable chat-sr
| Capture initial PC to determine if chat is running in ram or flash.
variable chat-pc
: get-status ( - dp) resync c.GetStatus -rot chat-sr ! chat-sp ! ;
: set-sp-and-run ( pc dp) chat-sp @ c.SetAddr chat-sr @ swap c.Run ;
: c.Hello ( - in-ram?)
#115200 bps resync
cr ." Chat firmware version " get-version
radix preserve hex sep preserve -sep <# 4# 4# #> type
get-status drop ( set up chat-sp and chat-sr for later)
chat-sp @ 4 + c.SetAddr 1 c.ReadWords w> ( initial pc) @boot u< ;
| NOTE: We don't define RunWait separately. Since we will always be reading
| the registers back after Run, that first read command will block until
| the target is ready.
: chat
chat-via c.Hello get-status set-sp-and-run
c.ReadChunk c.WriteChunk c.ErasePage c.FlashChunk ;