-
Notifications
You must be signed in to change notification settings - Fork 12
/
MBPROTO
125 lines (104 loc) · 3.15 KB
/
MBPROTO
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
\ STM8 eForth MODBUS protocol handler - intended to run as an IDLE task
#require MBBASE
#require ]B!
NVM
VARIABLE mbnode \ MODBUS node id
VARIABLE crcerr \ CRC error counter
VARIABLE mbpre \ xt for FC preparation (e.g. reading inputs)
VARIABLE mbact \ xt for output action (e.g. output, debugging)
VARIABLE mbdef \ xt for default handler
\ flag MODBUS Exception and set code
: MBEC ( ec -- )
[ 1 rtbuf 1+ 7 ]B! \ flag error in FC field
( ec ) txc+ \ and put EC
;
\ true if n in range mbp1,mbp2, else false and MODBUS EC=2
: mbrange? ( n -- b )
-1 ( b ) SWAP mbp1 mbp2 + - 0< IF
2 MBEC ( b ) NOT
THEN
;
\ default FC handler - raise EC 1 "ILLEGAL FUNCTION"
: FCDEF ( -- )
mbdef @ ?DUP IF
\ maybe there is something else you want to try
( xt ) EXECUTE
ELSE
1 MBEC
THEN
;
\ make FC-XT Table for FC>XT, initialize with "default FC handler"
HERE ( [ tab ] ) ' FCDEF ( [ a1 a2 ] )
DUP , DUP , DUP , DUP , DUP , DUP , DUP , DUP ,
DUP , DUP , DUP , DUP , DUP , DUP , DUP , ,
\ turn FC into XT table address
: FC>XT ( fc -- a )
\ map FC17 to FC24 to FC-XT table index 6..13 (see issue #47)
DUP 17 < IF 1- ELSE 11 - THEN
2* ( [ tab ] ) LITERAL +
;
\ get MODBUS FC
: mbfc ( -- c )
rtbuf 1+ C@
;
\ MODBUS protocol handler
: MBPROTO ( -- )
rtbuf rxp @ - ( rx )
1 TIM tstamp @ - < AND ( message trigger )
IF
rxp @ 2- ( a1 ) DUP rtbuf ( a1 a1 a0 )
MBCRC ( a1 crc-le ) SWAP @ = ( crc OK )
( crc-ok ) IF
mbnode @ rtbuf C@ = IF \ node address match
rtbuf 2+ 2@ ( mbp2 mbp1 ) mbp 2! \ keep MODBUS parameter
mbpre @?EXEC \ preparation handler, e.g. read inputs
mbfc ( fc ) DUP 1 25 WITHIN IF
FC>XT @?EXEC \ get and execute FC handler
ELSE
FCDEF \ default handler
THEN
tbp @ rtbuf ( a1 a0 ) MBCRC ( CRC-LE ) tx+
mbact @?EXEC \ action handler, e.g. write outputs
send
THEN
ELSE
1 crcerr +!
THEN
rxres
THEN
;
RAM
\ To speed up MODBUS server development:
\ * load MBPROTO manually
\ * #require and run PERSIST
\ RESET will then go back to this point :-)
\\ Example
\ Minimal MODBUS server with a FC06 "Write Single Register" handler
#require MBPROTO
RAM
#require WIPE
#require MBRESET
MBRESET \ Reset the MODBUS Function Code table
#require :NVM
#require 'IDLE
NVM
#require MBDUMP
\ --- FC06 handler "Write Single Register"
:NVM ( -- )
\ write register address and value to the console
." Write register:" mbp1 . ." =" mbp2 . CR
MBWR \ acknowledge FC06
;NVM ( xt ) 6 FC>XT ! \ register the FC handler
: showfc ( -- )
rtbuf 1+ C@ ." FC:" . CR
1 MBEC \ set error code
;
: init ( -- )
0 UARTISR \ init UART handler w/ default baud rate
1 mbnode ! \ set node address
[ ' showfc ] LITERAL mbdef ! \ FC default action (optional feature)
[ ' MBDUMP ] LITERAL mbact ! \ show buffers (debug demo)
[ ' MBPROTO ] LITERAL 'IDLE ! \ run MB protocol handler as idle task
;
' init 'BOOT !
WIPE RAM