forked from dan4thewin/FreeForth2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathff43.ff
1955 lines (1802 loc) · 93.4 KB
/
ff43.ff
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/ff needs
\ $Id: ff43.ff,v 1.14 2009-06-15 20:39:15 lavarec Exp $
."+_ff43_-_FreeForth_development_environment_for_MSP430_micro-controllers^J"
\ Definitions of terms used in this source file:
\
\ + host:
\ PC workstation on which this source file is compiled, providing human
\ interface and compilation resources during target application development
\
\ + target:
\ MSP430 microcontroler for which application code is cross-compiled by host
\
\ + host image of target memory:
\ host buffer mirroring target memory, into which the host cross-compiles
\ target code and data, while marking modified target addresses into an
\ "update" host buffer, which is reset when the target memory is updated
\ by downloading code and data marked in the update buffer
\
\ + umbilical link:
\ serial link connecting host and target during target code development and
\ debug, allowing the host to communicate with a target monitor
\
\ + target monitor:
\ target program allowing the host either to download, from host image to
\ target memory, code and data marked in the update buffer, or to upload
\ code and data from target memory to host image for dump or disassembly,
\ or to request target to start execution from a downloaded address
\
\ + incremental edit/compile/load/execute:
\ interactive development technique supported by integrated development tools
\ able to keep their context over several edit/compile/load/execute cycles:
\ while the target executes the monitor in parallel with the application code
\ (thanks to a simple multitasker and/or interrupts), the host interacts with
\ the developper to edit a command line, then compiles it on top of the
\ compilation context resulting from the previous cycles, and, when finishing
\ the compilation of an "anonymous" subroutine, updates the target memory
\ context by downloading all the code and data marked in the update buffer
\ since the previous download, and requests the target monitor to execute
\ a call to the anonymous subroutine
\
\ + anonymous subroutine:
\ a "named" subroutine entry point is defined (with "A:") by a label, which
\ is a symbolic constant equal to the subroutine entry point address, which
\ may be (backward-only) referenced in later compiled code or data;
\ an "anonymous" subroutine entry point is not declared by a label, but
\ implicitely defined by the end of the previous subroutine (see ";A");
\ as an anonymous subroutine cannot be later referenced, it must be "used"
\ immediately: as soon as its ending ";A" is compiled, it is downloaded
\ (together with all code and data compiled since the last download) into
\ target memory, then the target is requested to call its entry point, and
\ the host compilation pointer is moved back to this entry point, so the
\ execute-once anonymous subroutine code space may be reused
\
\ + ROM BootStrapLoader (aka "ROMBSL", see TI application report slaa089c.pdf):
\ target monitor residing in MSP430 boot ROM (address range $0C00-$0FFF),
\ executed at reset after the sequence: MSP.RST low, MSP.TCK high-low twice,
\ and MSP.RST high; it is a software UART polling (i.e. interrupt disabled)
\ P1.1=BSLTX to transmit and P2.2=BSLRX to receive 8bits/evenParity/1stop
\ at autobaud upto 9600 bps in halfduplex with specific framing protocol;
\ unhappily, this ROM BSL is bugged (its checksum verification has the nasty
\ side effect to write to the address corresponding to the checksum value),
\ so it can only be used with great care
\
\ + RAM BootStapLoader (aka "RAMBSL"):
\ target monitor downloaded into target RAM with the help of the ROM BSL,
\ to overcome the ROMBSL bugs and speedup the communication with host
\ to initialize the target flash memory;
\ it is a software UART polling the same BSLTX and BSLRX to communicate
\ 8bits/noParity/1stop at 115200 bps in halfduplex with BLD protocol
\
\ + BLD protocol:
\ transfer units are 16-bits words, LSByte1st MSByte2nd ("littelEndian");
\ each transaction begins with the target sending one "synchro" byte, telling
\ host that target is ready for a new transaction; then host sends two words,
\ an ADDRESS and a COUNT:
\ . if COUNT is null:
\ if ADDRESS is null, transaction is finished, target sends its synchro,
\ otherwise target executes a call at ADDRESS, transaction ends on return
\ . otherwise if COUNT is even:
\ host downloads COUNT/2 words that target writes sequentially from ADDRESS
\ . otherwise COUNT is odd:
\ host uploads COUNT/2 words that target reads sequentially from ADDRESS
\ Note that target writes/reads 16-bits words, then the MSP430 SFR address
\ range (0-255), which is only byte-accessible, cannot be directly accessed
\ by BLD protocol; however, it is indirectly accessible by downloading and
\ executing code that byte-accesses the SFR address range.
\
\ + FLASH BootLoaDer:
\ target monitor downloaded into target flash memory (usually by RAM
\ BootStrapLoader) implementing an UART 8bits/noParity/1stop at 115200 bps
\ in halfduplex with BLD protocol, with interrupts disabled to allow flash
\ interrupt vectors to be erased and reprogrammed;
\ depending on FLDUART compilation constant, it may be either a software UART
\ polling BSLTX and BSLRX (FLDUART=-1 for MSPs with no hardware UART), or the
\ hardware UART0 (FLDUART=0 for MSPs with no UART1) or UART1 (FLDUART=1 for
\ MSPs using UART0 as hardware SPI port);
\ at reset, the target transmits a "ready" byte on the UART to the host:
\ if the host immediately echoes the byte, the target executes the FLASH
\ BootLoader, otherwise, after a delay of 156ms without echo, the target
\ start executing application code (which in turn may execute an interrupt-
\ driven target monitor as one of its tasks for debugging).
\ This single file provides:
\ + an MSP430 incremental/interactive macro-assembler
\ + an MSP430 interactive disassembler (see "@DIS")
\ + an MSP430 ROMBSL interactive interface (to be used with great care)
\ + a disassembly of MSP430F147 ROM (for full understanding of ROMBSL bugs)
\ + an MSP430 RAMBSL for fast flash programming at 115200bps
\ + an MSP430 Flash BootLoaDer with a choice of 3 different polling UARTs
\ + a set of MSP430 memory and peripherals live-state dumping tools
\ + TI.txt and Intel.hex file formats converters into or from host image
\ The compilation of this file is conditionned by a few constants and words
\ which get default values if not defined before compiling this file:
\ RESETuart, BSLPORT, BLDPORT, MSPTYPE, FLDUART, INIFLASH
\ Look for "[~]" to find them and their associated comments in this file.
\ PC UARTs use (see ff.ff for PC UARTs interface):
\ As the GPIO ports used for MSP.ROMBSL.UART (P1.1=BSLTX and P2.2=BSLRX)
\ are different from those used for MSP.UART0 (P3.4=UTXD0 and P3.5=URXD0),
\ and different from those used for MSP.UART1 (P3.6=UTXD1 and P3.7=URXD1),
\ the PC UART used to communicate with MSP.ROMBSL.UART cannot be also used
\ to communicate with MSP.UART0 or MSP.UART1:
\ + PC.uart1.BSLPORT (i.e. "1 uart! BSLPORT port!") is used for MSP.ROMBSL.UART
\ + PC.uart0.BLDPORT (i.e. "0 uart! BLDPORT port!") is used for MSP.UART0or1
\ Moreover, as MSP.RST and MSP.TCK must be driven in a specific sequence to
\ activate the ROMBSL, depending on the UARTs cables interconnexions, they
\ may be driven either by PC.uart1 (RESETuart=1) or by PC.uart0 (RESETuart=0);
\ see the definitions of RST0 RST1 and TCK0 TCK1 for the default PC.RESETuart
\ signals assignments (DTR to RST and RTS to TCK, both inverted by V24 voltage
\ translators), that you can define differently before loading this file.
\ --------------------------------------------------------------------------
\ TODO:
\ + add more checkings depending on MSPTYPE
\ --------------------------------------------------------------------------
."+_ASM43_-_MSP430_AsSeMbler^J"
\ UG="User's Guide"(slau049.pdf)
\ Instruction set format(UG5.3p82): F E D C B A 9 8 7 6 5 4 3 2 1 0
\ + double operand instructions: op.code src.reg AdBwAsrc dst.reg
\ + single operand instructions: 0 0 0 1 -op.code-- BwAdst dst.reg
\ + un/conditional instructions: 0 0 1 -cond- -----jump.offset-----
\ Instruction map(UG5.4p87):
\ 1000 RRC 1080 SWPB 1100 RRA 1180 SXT 1200 PUSH 1280 CALL 1300 RETI
\ 1040 RRC.B 1140 RRA.B 1240 PUSH.B
\ 2000 JNZ 2800 JNC 3000 JN 3800 JL
\ 2400 JZ 2C00 JC 3400 JGE 3C00 JMP
\ 4000 MOV 6000 ADDC 8000 SUB A000 DADD C000 BIC E000 XOR
\ 5000 ADD 7000 SUBC 9000 CMP B000 BIT D000 BIS F000 AND
\ Registers(UG5.1p66): R0=PC R1=SP R2=SR/CG1 R3=CG2 R4..R15
\ PC and SP must be even.
\ SP: POP SP (i.e. MOV @R1+,R1) ignores "+", equivalent to MOV @R1,R1
\ SR: F-9:reserved 8:V 7:SCG1 6:SCG0 5:OSCoff 4:CPUoff 3:GIE 2:N 1:Z 0:C
\ CG1: Asrc=0:reg 1:(0) 2:+4 3:+8
\ CG2: Asrc=0:+0 1:+1 2:+2 3:-1
\ Addressing modes(UG5.2p71): Asrc|Adst(0..3) or Ad(0..1)
\ 0:Rn 1:X(Rn)[X(R0):$sym,X(R2):&abs] 2:@Rn 3:@Rn+[@R0+:#imm]
\ sym: offset relative to the address where the offset is stored
\ Clock cycles(UG3-72): un/cond:2
\ 2op(Asrc/Ad): 0/0:1 2/0:2 3/0:2 1/0:3 0/1:4 2/1:5 3/1:5 1/1:6 dstPC:+1
\ 1op(Asrc/PUSH/CALL): 0:1/3/4 1:4/5/5 2:3/4/4 3:3/4/5 Jx:2 RETI:5+IRQ:6
\ ------------------------------------------------------------------------
\ MSP430 64pins pinout:
\
\ PCDTR>RST-----------------------+ +---------------------------TCK<PCRTS
\ P6.0/A0 -----+ | | +----- TDO/TDI
\ P6.1/A1 ---+ | | | | +--- XT2IN
\ P6.2/A2 -+ | | | | | | +- XT2OUT
\ AVss -----+ | | |RST/NMI | | | +------- P5.7/TBoutH
\ DVss ---+ | | | | | |TMS | | | | +----- P5.6/ACLK
\ AVcc -+ | | | | | |TCK|TDI| | | | | +--- P5.5/SMCLK
\ 6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 4
\ 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9
\ DVcc 1 48 P5.4/MCLK
\ P6.3/A3 2 47 P5.3/UCLK1
\ P6.4/A4 3 46 P5.2/SOMI1
\ P6.5/A5 4 45 P5.1/SIMO1
\ P6.6/A6 5 44 P5.0/STE1
\ P6.7/A7 6 43 P4.7/TBCLK
\ Vref+ 7 42 P4.6/TB6
\ XIN 8 MSP430F13x 41 P4.5/TB5
\ XOUT/TCLK 9 MSP430F14x 40 P4.4/TB4
\ Veref+ 10 39 P4.3/TB3
\ V(e)ref- 11 38 P4.2/TB2
\ P1.0/TACLK 12 37 P4.1/TB1
\ <BSLTX P1.1/TA0 13 36 P4.0/TB0
\ P1.2/TA1 14 35 P3.7/URXD1(F14x)<
\ P1.3/TA2 15 34 P3.6/UTXD1(F14x)>
\ P1.4/SMCLK 16 33 P3.5/URXD0<
\ 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3
\ 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
\ P1.5/TA0 -+ | | | | | | | | | | | | | | +--- P3.4/UTXD0>
\ P1.6/TA1 ---+ | | | | | | | | | | | | +----- P3.3/UCLK0
\ P1.7/TA2 -----+ | | | | | | | | | | +------- P3.2/SOMI0
\ P2.0/ACLK --+ | | | | | | | | +--------- P3.1/SIMO0
\ P2.1/TAINCLK -+ | | | | | | +----------- P3.0/STE0
\ >BSLRX P2.2/CAOUT/TA0 -+ | | | | +-------- P2.7/TA0
\ P2.3/CA0/TA1 -----+ | | +---------- P2.6/ADC12CLK
\ P2.4/CA1/TA2 -------+ + ----------- P2.5/Rosc
\ ------------------------------------------------------------------------
\ MSP430F11x2 20pins pinout:
\
\ +--------------+
\ TEST | 1 20 | P1.7/TA2/TDO/TDI
\ VCC | 2 19 | P1.6/TA1/TDI/TCLK
\ Rosc/P2.5 | 3 18 | P1.5/TA0/TMS
\ VSS | 4 17 | P1.4/SMCLK/TCK <PCRTS
\ XOUT | 5 MSP430 16 | P1.3/TA2
\ XIN | 6 F11x2 15 | P1.2/TA1
\ PCDTR> RST/NMI | 7 14 | P1.1/TA0 BSLTX>PCRXD
\ ACLK/A0/P2.0 | 8 13 | P1.0/TACLK/ADC10CLK
\ INCLK/A1/P2.1 | 9 12 | P2.4/TA2/A4/VREF+/VeREF+
\ PCTXD>BLSRX TA0/A2/P2.2 | 10 11 | P2.3/TA1/A3/VREF-/VeREF-
\ +--------------+
\ ------------------------------------------------------------------------
\ Host memory image of MSP430 memory:
create mem $18000 allot ; mem $18000 0 fill \ cache and changed marks
mem $1000+ $F000 $FF fill \ flash address range, initialized virgin
: `@ dup $FFFF0001& 0= drop IF mem+ ;THEN !"invalid_MSP430_address"
: _@ `@ w@ ; \ m@ -- w
: _! `@ tuckw! 1 swap mem- 2/ mem+ $10000+ c! ; \ w m@ --
\ Host memory image inspection tools for assembler debug:
: 2wdump \ end @ --
dup .w .":" dup 16+ -rot \ -- lim end @
START >rswapr> = IF nip cr 2wdump ;THEN >rswapr>
\ dup 7& 0= drop IF space THEN \ not practical for @DIS
space dup _@ .w 2+
ENTER u<= UNTIL 2drop drop space ;
: ;wdump` ;` \ @ -- ; CR to get next 16, space+CR to exit
BEGIN 16 bounds under 2wdump stopdump? UNTIL drop ;
: wdump bounds 2wdump cr ; \ @ # --
\ Process changed parts of host memory image:
:^ .changed swap .w ."+" .w space ; \ @ # -- ; process run of changed words
: .all` \ -- ; scan mem for runs of changed words
mem $10000+ $8000 bounds BEGIN u> WHILE c@+ 0- drop TILL 1- tuck
BEGIN 1+ u> WHILE dupc@ 0- drop 0= UNTIL >rswapr> \ -- @end @1st @afterLast
tuck over- 2* swap mem- $10000- 2* swap .changed REPEAT 2drop
: mrst mem $10000+ $8000 erase ; \ clear mem-changes
\ Basic compilation support:
variable _p \ compilation allocation pointer
variable `i \ last compiled instruction pointer
: `o _p@ `i! \ op -- ; compile opcode
: _,` ;` _p@ _! 2 _p +! ; \ n -- ; compile 1 word
: `B $40 \ convert last compiled instruction to byte addressing mode
: `i+! `i@ tuck _@ | swap _! ; \ mask -- ; patch last compiled instruction
\ Srce addressing modes:
: $,` ;` _p@ - _,` $010 \ a -- ; symbolic srce addressing mode (PC),
: `s `i@ _@ $C000& drop `i+! ? !"not_for_single_operand_instruction"
: `si >r ;` _,` r> `s ; \ a m -- ; indexed srce addressing mode
: &,` ;` _,` $210 `s ; \ a -- ; absolute srce addressing mode (R2),
\ Constant-generators addressing modes are used for 6 small constants:
create `cg, $3000000 , $3100001 , $3200002 , $330FFFF , $2200004 , $2300008 ,
: #,` ;` $FFFF& \ n -- ; immediate srce addressing mode @PC+,
`cg, 6 TIMES w@+ rot = nip swap IF nip rdrop w@ `s ;THEN 2+ REPEAT drop
_,` $030 `s ;
\ Dest addressing modes:
: `rslv \ @src @dst -- ; resolve conditional jump offset
over- 2/ 1- dup 2* over^ -$400& drop IF !"jump_off_range" ;THEN
$3FF& over _@ $FC00& | swap _! ;
variable `dmask \ selects fields
: `RL? `dmask@ $FBF& $FBF- drop ; \ RLA RLC
: $` ;` \ a -- ; symbolic dest addressing mode (PC)
`RL? 0= IF dup $,` THEN \ RLA RLC
`dmask@ 0- 0= drop IF `i@ swap `rslv ;THEN \ conditional jump
_p@ - _,` $090
: `d `dmask@ 0- 0= IF !"$symbolic_addressing_mode_expected" ;THEN
2dup ~ & $20& 0= drop IF & `i+! ;THEN
!"not_for_double_operand_instruction"
: `di >r ;` \ a m -- ; indexed dest addressing mode
`RL? 0= IF 0 over `si THEN _,` r> `d ;
: &&` ;` \ a -- ; absolute dest addressing mode (R2)
`RL? 0= IF dup &,` THEN _,` $292 `d ;
\ Constant-generators addressing modes are used for 4 small constants:
\ bug'CPU4': "PUSH 4 #" and "PUSH 8 #" must not be implemented with CG1
create `cg $0030000 , $0130001 , $0230002 , $033FFFF , \ $0220004 , $0320008 ,
: #` ;` $FFFF& \ n -- ; immediate dest addressing mode @PC+ PUSH/CALL
`cg 4 TIMES w@+ rot = nip swap IF nip rdrop w@ `d ;THEN 2+ REPEAT drop
_,` $030 `d ;
\ Srce registers:
: PC,` $000 `s ; : (PC),` $010 `si ; : @PC,` $020 `s ; : @PC+,` $030 `s ;
: SP,` $100 `s ; : (SP),` $110 `si ; : @SP,` $120 `s ; : @SP+,` $130 `s ;
: SR,` $200 `s ; \ other addressing modes dedicated to constant generator
: R4,` $400 `s ; : (R4),` $410 `si ; : @R4,` $420 `s ; : @R4+,` $430 `s ;
: R5,` $500 `s ; : (R5),` $510 `si ; : @R5,` $520 `s ; : @R5+,` $530 `s ;
: R6,` $600 `s ; : (R6),` $610 `si ; : @R6,` $620 `s ; : @R6+,` $630 `s ;
: R7,` $700 `s ; : (R7),` $710 `si ; : @R7,` $720 `s ; : @R7+,` $730 `s ;
: R8,` $800 `s ; : (R8),` $810 `si ; : @R8,` $820 `s ; : @R8+,` $830 `s ;
: R9,` $900 `s ; : (R9),` $910 `si ; : @R9,` $920 `s ; : @R9+,` $930 `s ;
: R10,` $A00 `s ; : (R10),` $A10 `si ; : @R10,` $A20 `s ; : @R10+,` $A30 `s ;
: R11,` $B00 `s ; : (R11),` $B10 `si ; : @R11,` $B20 `s ; : @R11+,` $B30 `s ;
: R12,` $C00 `s ; : (R12),` $C10 `si ; : @R12,` $C20 `s ; : @R12+,` $C30 `s ;
: R13,` $D00 `s ; : (R13),` $D10 `si ; : @R13,` $D20 `s ; : @R13+,` $D30 `s ;
: R14,` $E00 `s ; : (R14),` $E10 `si ; : @R14,` $E20 `s ; : @R14+,` $E30 `s ;
: R15,` $F00 `s ; : (R15),` $F10 `si ; : @R15,` $F20 `s ; : @R15+,` $F30 `s ;
\ Dest registers:
: PC` $000 `d ; : (PC)` $090 `di ; : @PC` $020 `d ; : @PC+` $030 `d ;
: SP` $101 `d ; : (SP)` $191 `di ; : @SP` $121 `d ; : @SP+` $131 `d ;
: SR` $202 `d ; \ other addressing modes dedicated to constant generator
: R4` $404 `d ; : (R4)` $494 `di ; : @R4` $424 `d ; : @R4+` $434 `d ;
: R5` $505 `d ; : (R5)` $595 `di ; : @R5` $525 `d ; : @R5+` $535 `d ;
: R6` $606 `d ; : (R6)` $696 `di ; : @R6` $626 `d ; : @R6+` $636 `d ;
: R7` $707 `d ; : (R7)` $797 `di ; : @R7` $727 `d ; : @R7+` $737 `d ;
: R8` $808 `d ; : (R8)` $898 `di ; : @R8` $828 `d ; : @R8+` $838 `d ;
: R9` $909 `d ; : (R9)` $999 `di ; : @R9` $929 `d ; : @R9+` $939 `d ;
: R10` $A0A `d ; : (R10)` $A9A `di ; : @R10` $A2A `d ; : @R10+` $A3A `d ;
: R11` $B0B `d ; : (R11)` $B9B `di ; : @R11` $B2B `d ; : @R11+` $B3B `d ;
: R12` $C0C `d ; : (R12)` $C9C `di ; : @R12` $C2C `d ; : @R12+` $C3C `d ;
: R13` $D0D `d ; : (R13)` $D9D `di ; : @R13` $D2D `d ; : @R13+` $D3D `d ;
: R14` $E0E `d ; : (R14)` $E9E `di ; : @R14` $E2E `d ; : @R14+` $E3E `d ;
: R15` $F0F `d ; : (R15)` $F9F `di ; : @R15` $F2F `d ; : @R15+` $F3F `d ;
\ Single operand instructions: use with dest register or addressing mode
: `o1 $3F `dmask! `o ; \ V N Z C
: RRC` $1000 `o1 ; : RRC.B` RRC` `B ; \ 0 * * *
: RRA` $1100 `o1 ; : RRA.B` RRA` `B ; \ 0 * * *
: PUSH` $1200 `o1 ; : PUSH.B` PUSH` `B ; \ - - - -
: SWPB` $1080 `o1 ; : SXT` $1180 `o1 ; \ - - - - 0 * * ~Z
: RETI` $1300 `o1 ; variable `callmrk
: CALL` $1280 `o1 `i@ `callmrk! ;
\ Conditional jumps: use with $symbolic addressing mode only, backward ref only
: `o0 0 `dmask! `o ;
: JZ` $2400 `o0 ; : JNZ` $2000 `o0 ; \ Z=1 Z=0
: JC` $2C00 `o0 ; : JNC` $2800 `o0 ; \ C=1 C=0 C:u< NC:u>=
: JN` $3000 `o0 ; : JGE` $3400 `o0 ; \ N=1 N^V=0 L:< GE:>=
: JL` $3800 `o0 ; : JMP` $3C00 `o0 ; \ N^V=1 uncond
JZ` ' alias JEQ` \ EQual
JNZ` ' alias JNE` \ Non Equal
JC` ' alias JHS` \ Higher or Same (unsigned)
JNC` ' alias JLO` \ LOwer (unsigned)
\ WARNING: comparisons are from right to left: CMP R0, R1 JL=jmpifR1<R0
\ Double operand instructions: use with src and dest reg or addressing mode
: `o2 $8F `dmask! `o ; \ V N Z C
: MOV` $4000 `o2 ; : MOV.B` MOV` `B ; \ - - - -
: ADD` $5000 `o2 ; : ADD.B` ADD` `B ; \ * * * *
: ADDC` $6000 `o2 ; : ADDC.B` ADDC` `B ; \ * * * *
: SUBC` $7000 `o2 ; : SUBC.B` SUBC` `B ; \ * * * *
: SUB` $8000 `o2 ; : SUB.B` SUB` `B ; \ * * * *
: CMP` $9000 `o2 ; : CMP.B` CMP` `B ; \ * * * *
: DADD` $A000 `o2 ; : DADD.B` DADD` `B ; \ ? * * * C=result>$9999
: BIT` $B000 `o2 ; : BIT.B` BIT` `B ; \ 0 * * ~Z
: BIC` $C000 `o2 ; : BIC.B` BIC` `B ; \ - - - -
: BIS` $D000 `o2 ; : BIS.B` BIS` `B ; \ - - - -
: XOR` $E000 `o2 ; : XOR.B` XOR` `B ; \ * * * ~Z V=bothOp<0
: AND` $F000 `o2 ; : AND.B` AND` `B ; \ 0 * * ~Z
\ Emulated instructions: use with dest register or addressing mode
: POP` MOV` @SP+,` ; : POP.B` POP` `B ;
: ADC` ADDC` 0 #,` ; : ADC.B` ADC` `B ;
: DADC` DADD` 0 #,` ; : DADC.B` DADC` `B ;
: DEC` SUB` 1 #,` ; : DEC.B` DEC` `B ;
: DECD` SUB` 2 #,` ; : DECD.B` DECD` `B ;
: INC` ADD` 1 #,` ; : INC.B` INC` `B ;
: INCD` ADD` 2 #,` ; : INCD.B` INCD` `B ;
: SBC` SUBC` 0 #,` ; : SBC.B` SBC` `B ;
: INV` XOR` -1 #,` ; : INV.B` INV` `B ;
: CLR` MOV` 0 #,` ; : CLR.B` CLR` `B ;
: TST` CMP` 0 #,` ; : TST.B` TST` `B ;
: RLA` ADD` $FBF `dmask! ; : RLA.B` RLA` `B ; \ src=dst
: RLC` ADDC` $FBF `dmask! ; : RLC.B` RLC` `B ; \ src=dst
: CLRC` BIC` 1 #,` SR` ; : SETC` BIS` 1 #,` SR` ;
: CLRZ` BIC` 2 #,` SR` ; : SETZ` BIS` 2 #,` SR` ;
: CLRN` BIC` 4 #,` SR` ; : SETN` BIS` 4 #,` SR` ;
: DINT` BIC` 8 #,` SR` ; : EINT` BIS` 8 #,` SR` ;
: BR` MOV` PC` $F30 `dmask! ; \ dst->src
: NOP` $4303 _,` ; \ MOV#0,R3
\ RET` automatically optimizes tail-recursion:
: "",` ;` 1+ 2/ TIMES w@+ _,` REPEAT drop \ "" -- ; compile a literal string
: -opt` 0 `callmrk! ; \ -- ; prevent next RET` tail-recursion optimization
: RET` `i@ `callmrk@ <> 2drop IF MOV` @SP+,` PC` ;THEN \ regular return
`i@ _@ $12B0- 0= drop \ CALL#?
IF `i@ 2+ dup _@ swap - dup 2/ ^ -$400& 0= drop \ offset in range?
IF `i@ dup _p! JMP` _p@ _@ `rslv ;THEN \ short relative jump
THEN `i@ dup _@ dup $F& $100* swap $30& | $4000| swap _! ; \ CALL->BR
variable `anon \ stores entry point of anonymous subroutine
: cleanup` \ -- ; removes last def after error
`anon@ 0- 0= IF drop H@ dup@ swap 5+ c@+ + H! THEN
: org` ;` dup _p! `anon! ; $200 org` \ start of ram
: .H` _p@ `anon@ 0- 0= IF drop H@ @ THEN 2wdump ;
\ Interactivity layer:
:^ _execute wdump ' .changed !^ .all` ."call_$" .w ; \ default: wdump
: ;A` \ -- ; closes a subroutine, named or anonymous
`anon@ _p@ <> drop IF RET` \ -- @ ; non-empty: close subroutine
0- IF dup _p! _execute over THEN \ -- * ; deallocate before execute
THEN drop _p@ `anon! ; \ open new anonymous subroutine
: A:` \ <name> -- ; creates an assembler label: use with any addressing mode
;` `anon@ 0- drop IF ;A` 0 `anon! THEN \ flush anonymous
_p@ equ` 0 `callmrk! ;
\ Control structures:
JZ` ' alias NZ?` JNZ` ' alias Z?` \ Z=1 Z=0
JZ` ' alias NE?` JNZ` ' alias EQ?`
JC` ' alias NC?` JNC` ' alias C?` \ C=1 C=0
JC` ' alias LO?` JNC` ' alias HS?`
JL` ' alias GE?` JGE` ' alias L?` \ N^V=1 N^V=0
JN` ' alias NN?` \ no N opposite \ N=1
: @IF` `dmask@ 0- 0= drop IF `i@ ;THEN !"jump-condition_missing" \ -- @
: @SKIP` JMP` @IF` `B ; \ -- @ ; `B to differ from START`
: @ELSE` @SKIP` swap \ @ -- @'
: @THEN` _p@ `rslv 0 `callmrk! ; \ @ --
: ;@THEN` RET` @THEN` ;
variable `mrk \ -mrk +mrk
: @START` JMP`
: @BEGIN` `mrk@ _p@ $1'0001* `mrk! ;
: @ENTER` `mrk w@ 2- dup _@ $3C00- 0= drop IF @THEN` ;THEN !"START_missing"
: @WHILE` @IF`
: `+jmp `mrk 2+ 2dup w@ `rslv w! ; \ backward-link forward-refs
: @BREAK` @ELSE` `+jmp ;
: @TILL` @IF`
: `-jmp `mrk w@ `rslv ;
: @AGAIN` @ELSE` `-jmp ;
: @UNTIL` @TILL`
: @END` `mrk w@+ swap w@ \ -- mrk -mrk +mrk
START dup _@ over @THEN` -$400| 1+ 2* + \ backward-link offset always<0
ENTER = UNTIL 2drop `mrk! ;
: @REPEAT` JMP` @IF` `-jmp @END` ;
16 base!
variable _d $300 _d! \ data ram allocation pointer
: BUF:` ;` _d@ equ` _d +! ; \ n <name> -- ; creates a buffer of n bytes
\ ---------------------------------------------------------
."+_MMR43_-_MSP430_Memory_Mapped_Registers^J"
\ Bit/mask definers, for use after MOV BIT BIS BIC XOR
: `bi r> `B c@+ #,` c@ &&` ;
: b:` :` `bi ' call, c, c, anon:` ; \ addr mask <name> --
: .0:` ;` $01 b:` ; : .1:` ;` $02 b:` ; : .2:` ;` $04 b:` ; : .3:` ;` $08 b:` ;
: .4:` ;` $10 b:` ; : .5:` ;` $20 b:` ; : .6:` ;` $40 b:` ; : .7:` ;` $80 b:` ;
\ --------------------------
\ 0000+100: Byte Peripherals
\ 0000+10: Special Function Registers:
\ 7 6 5 4 3 2 1 0
$0 equ IE1 \ UTXIE0 URXIE0 ACCVIE NMIIE OFIE WDTIE
$1 equ IE2 \ UTXIE1 URXIE1
$2 equ IFG1 \ UTXIFG0 URXIFG0 NMIIFG OFIFG WDTIFG
$3 equ IFG2 \ UTXIFG1 URXIFG1
$4 equ ME1 \ UTXE0 URXE0=USPIE0
$5 equ ME2 \ UTXE1 URXE1=USPIE1
\ 7 6 5 4 3 2 1 0
IE1 .7: UTXIE0` IE1 .6: URXIE0` IE1 .5: ACCVIE` IE1 .4: NMIIE`
IE2 .5: UTXIE1` IE2 .4: URXIE1` IE1 .1: OFIE` IE1 .0: WDTIE`
IFG1 .7: UTXIFG0` IFG1 .6: URXIFG0` IFG1 .1: OFIFG` IFG1 .0: WDTIFG`
IFG2 .5: UTXIFG1` IFG2 .4: URXIFG1`
ME1 .7: UTXE0` ME1 .6: URXE0` URXE0` ' alias USPIE0`
ME2 .5: UTXE1` ME2 .4: URXE1` URXE1` ' alias USPIE1`
\ 0010+10: Digital I/O port P3 and P4 control (PxDIR=0:in,1:out)
$18 equ P3IN $19 equ P3OUT $1A equ P3DIR $1B equ P3SEL
$1C equ P4IN $1D equ P4OUT $1E equ P4DIR $1F equ P4SEL
\ 0020+10: Digital I/O port P1 and P2 control (PxIES=0:_-,1:-_)
$20 equ P1IN $21 equ P1OUT $22 equ P1DIR $23 equ P1IFG
$24 equ P1IES $25 equ P1IE $26 equ P1SEL P1OUT .1: BSLTX`
$28 equ P2IN $29 equ P2OUT $2A equ P2DIR $2B equ P2IFG
$2C equ P2IES $2D equ P2IE $2E equ P2SEL P2IN .2: BSLRX`
\ 0030+10: Digital I/O port P5 and P6 control
$30 equ P5IN $31 equ P5OUT $32 equ P5DIR $33 equ P5SEL
$34 equ P6IN $35 equ P6OUT $36 equ P6DIR $37 equ P6SEL
\ 0048+03: ADC10 control (MSP430x11x2 and MSP430x12x2 only)
$48 equ ADC10DTC0 \ 8ADC10TB 4ADC10TC 2ADC10B1 1ADC10FETCH
$49 equ ADC10DTC1 \ number of transfers per block (0=disabled)
$4A equ ADC10AE
\ 0050+10: System clock generator and Comparator A
\ 7 6 5 4 3 2 1 0 BSLET
$56 equ DCOCTL \ DCO2 DCO1 DCO0 MOD4 MOD3 MOD2 MOD1 MOD0 80A7
$57 equ BCSCTL1 \ XT2OFF XTS DIVA1 DIVA0 0 RSEL2 RSEL1 RSEL0 8587
$58 equ BCSCTL2 \ SELM1 SELM0 DIVM1 DIVM0 SELS DIVS1 DIVS0 DCOR 0000
$59 equ CACTL1
$5A equ CACTL2
$5B equ CAPD
\ 0070+10: USART0 and USART1 (UG12.5p232)
\ USART0: 7 6 5 4 3 2 1 0
$70 equ U0CTL \ PENA PEV SP CHAR Listen SYNC MM SWRST
$71 equ U0TCTL \ CKPH CKPL SSEL1 SSEL0 URXSE TXWake STC TXEPT
$72 equ U0RCTL \ FE PE OE BRK URXEIE URXWIE RXWake RXERR
$73 equ U0MCTL \ Modulation Control Reg
$74 equ U0BR0 \ BaudRate low byte
$75 equ U0BR1 \ BaudRate high byte
$76 equ U0RXBUF
$77 equ U0TXBUF
\ USART1: 7 6 5 4 3 2 1 0
$78 equ U1CTL \ PENA PEV SP CHAR Listen SYNC MM SWRST
$79 equ U1TCTL \ free CKPL SSEL1 SSEL0 URXSE TXWake free TXEPT
$7A equ U1RCTL \ FE PE OE BRK URXEIE URXWIE RXWake RXERR
$7B equ U1MCTL \ Modulation Control Reg
$7C equ U1BR0 \ BaudRate low byte
$7D equ U1BR1 \ BaudRate high byte
$7E equ U1RXBUF
$7F equ U1TXBUF
\ 0080+10: ADC12 memory control: 80%EOS 40%VR- 30%VR+ 0f%INCH (%:ROwhen ENC=1)
$80 equ ADC12MCTL0 \ INCH=0:A0 VR+=0:AVcc
$81 equ ADC12MCTL1 \ INCH=1:A1 VR+=1:Vref+
$82 equ ADC12MCTL2 \ INCH=2:A2 VR+=2-3:VeRef+
$83 equ ADC12MCTL3 \ INCH=3:A3
$84 equ ADC12MCTL4 \ INCH=4:A4 VR-=0:AVss
$85 equ ADC12MCTL5 \ INCH=5:A5 VR-=1:Vref-/VeRef-
$86 equ ADC12MCTL6 \ INCH=6:A6
$87 equ ADC12MCTL7 \ INCH=7:A7
$88 equ ADC12MCTL8 \ INCH=8:VeRef+
$89 equ ADC12MCTL9 \ INCH=9:Vref-/VeRef-
$8A equ ADC12MCTL10 \ INCH=A:TemperatureSensor (Tsample > 30us)
$8B equ ADC12MCTL11 \ INCH=B-F:(AVcc-AVss)/2
$8C equ ADC12MCTL12
$8D equ ADC12MCTL13 \ INCH=A: V=0.00355*T(Celsius)+0.986(V) (use REF1V5)
$8E equ ADC12MCTL14
$8F equ ADC12MCTL15
\ ------------------------
\ 0100+80:Word Peripherals
$11E equ TBIV
$120 equ WDTCTL
\ 0128+08: Flash Control: (UGp415) B:1000+80, A:1080+80
\ Flash timing generator frequency must be in [257..476]kHz t=(FN+1)/MCLK
\ Program timings byte/word: single=35t blkFist=30t blkNext=21t blkLast=6t
\ Erase timings: MassErase=5297t PageErase=4819t
\ FCTL.MSByte(r/w)=$96/$A5 (UGC3.1p426)
\ FCTL 7 6 5 4 3 2 1 0
$128 equ FCTL1 \ SEGWRT WRT MEras Erase
$12A equ FCTL2 \ SSEL1 SSEL0 FN5 FN4 FN3 FN2 FN1 FN0
$12C equ FCTL3 \ EMEX Lock WAIT ACCVIFG KEYV BUSY
$12E equ TAIV
\ 0130+10: Multiplier
$130 equ MPY \ operand1, operation=Multiply
$132 equ MPYS \ operand1, operation=MultiplySigned
$134 equ MAC \ operand1, operation=MultiplyAccumulate
$136 equ MACS \ operand1, operation=MultiplyAccumulateSigned
$138 equ OP_2 \ operand2 (starts operation)
$13A equ ResLo
$13C equ ResHi
$13E equ SumExt
\ 0140+20: ADC12 conversion 0:Vin<=VR- FFF:Vin>=VR+ FFF*(Vin - VR-)/(VR+ - VR-)
$140 equ ADC12MEM0
$142 equ ADC12MEM1
$144 equ ADC12MEM2
$146 equ ADC12MEM3
$148 equ ADC12MEM4
$14A equ ADC12MEM5
$14C equ ADC12MEM6
$14E equ ADC12MEM7
$150 equ ADC12MEM8
$152 equ ADC12MEM9
$154 equ ADC12MEM10
$156 equ ADC12MEM11
$158 equ ADC12MEM12
$15A equ ADC12MEM13
$15C equ ADC12MEM14
$15E equ ADC12MEM15
\ 0160+20: Timer_A
$160 equ TACTL $170 equ TAR
$162 equ TACCTL0 $172 equ TACCR0
$164 equ TACCTL1 $174 equ TACCR1
$166 equ TACCTL2 $176 equ TACCR2
\ 0180+20: Timer_B
$180 equ TBCTL $190 equ TBR
$182 equ TBCCTL0 $192 equ TBCCR0
$184 equ TBCCTL1 $194 equ TBCCR1
$186 equ TBCCTL2 $196 equ TBCCR2
$188 equ TBCCTL3 $198 equ TBCCR3
$18A equ TBCCTL4 $19A equ TBCCR4
$18C equ TBCCTL5 $19C equ TBCCR5
$18E equ TBCCTL6 $19E equ TBCCR6
\ 01A0+10: ADC12 control and interrupt (%:ROwhen ENC=1)
\ Tsample > (Rext+2kOhm)*ln(2^13)*40pF+0.8us = Rext*0.36(us/kOhm)+1.52(us)
$1A0 equ ADC12CTL0 \ f000%SHT1 f00%SHT0 80%MSC 40%REF2V5 20%REFON
\ 10%ADC12ON 8ADC12OVIE 4ADC12TOVIE 2ENC 1ADC12SC
$1A2 equ ADC12CTL1 \ f000%CSTARTADD c00%SHS 200%SHP 100%ISSH
\ e0%ADC12DIV 18%ADC12SSEL 6CONSEQ 1ADC12BUSY
$1A4 equ ADC12IFG
$1A6 equ ADC12IE
$1A8 equ ADC12IV \ 0:noIRQ 2:MEMovrfl 4:ConvTimeOver 6+2*i=ADC12IFGi
\ 01B0+0C: ADC10 control (MSP430x11x2 and MSP430x12x2 only) (%:ROwhen ENC=1)
$1B0 equ ADC10CTL0 \ e000%SREF 1800%ADC10SHT 400%ADC10SR 200%REFOUT
\ 100%REFBURST 80%MSC 40%REF2V5 20%REFON 10%ADC10ON
\ 8ADC10IE 4ADC10IFG 2ENC 1ADC10SC
$1B2 equ ADC10CTL1 \ f000%INCH c00%SHS 200%ADC10DF 100%ISSH
\ e0%ADC10DIV 18%ADC10SSEL 6CONSEQ 1ADC10BUSY
$1B4 equ ADC10MEM \ 0:Vin<=VR-,3FF:Vin>=VR+,3FF*(Vin - VR-)/(VR+ - VR-)
$1BC equ ADC10SA \ $0200 on POR
\ -------------------------
\ 0200-...: Memory segments
$200 equ RAMstart \ end marker for disassembler
\ MSP430F1xx: F149 F148 F147 F135 F133 F1132
\ 0200+...: Ram +800 +800 +400 +200 +100 +100
\ 0C00+400: Boot memory +400 +400 +400 +400 +400 +400
\ 1000+100: Info flash +100 +100 +100 +100 +100 +100 (128 bytes sectors)
\ ...-FFFF: Main flash 1100 4000 8000 C000 E000 E000 (512 bytes sectors)
\ FFE0+020: Int. vect. +60K +48K +32K +16K +8K +8K (bootloader key)
\ Interrupt vectors:(priority) sourceModule moduleFlags
\ MSP430F149..133: MSP430F12x2,11x2:
\ FFE0:(0) (lowest) unused: good place for software version
\ FFE2:(1) P2 P2IFG0..P2IFG7 --
\ FFE4:(2) USART1tx UTXIFG1 P1 P1IFG0..P1IFG7
\ FFE6:(3) USART1rx URXIFG1 P2 P2IFG0..P2IFG7
\ FFE8:(4) P1 P1IFG0..P1IFG7 --
\ FFEA:(5) Timer_A3 CCIFG1 CCIFG2 TAIFG ADC10 ADC10IFG
\ FFEC:(6) Timer_A3 CCIFG0 USART0tx UTXIFG0 (12x2 only)
\ FFEE:(7) ADC12 ADC12IFG USART0rx URXIFG0 (12x2 only)
\ FFF0:(8) USART0tx UTXIFG0 Timer_A3 CCIFG1 CCIFG2 TAIFG
\ FFF2:(9) USART0rx URXIFG0 Timer_A3 CCIFG0
\ FFF4:(10) Watchdog WDTIFG Watchdog WDTIFG
\ FFF6:(11) Compar_A CAIFG --
\ FFF8:(12) Timer_B7 BCCIFG1..BCCIFG6 --
\ FFFA:(13) Timer_B7 BCCIFG0 --
\ FFFC:(14) NMI NMIIFG OFIFG ACCVIFG NMI NMIIFG OFIFG ACCVIFG
\ FFFE:(15) RST WDTIFG KEYV RST WDTIFG KEYV
\ -----------------------------------------------------------------------
."+_DIS43_-_MSP430_DISassembler^J"
variable `p \ points on next word
: `p@+ \ -- n ; get next word
`p@ _@ 2 `p +!
;
: `type \ @ # -- ; type string without trailing spaces
over+ BEGIN 1- dupc@ 32- drop UNTIL 1+ over- type
;
: `.sym \ n -- ; display memory-mapped-register symbol if defined between
>r \ first symbol (IE1=0) and last symbol (RAMstart=$200)
"IE1" find 2drop which@ "RAMstart" find 2drop which@ \ -- hlim h | == n
BEGIN dup@ r - 0= drop IF rdrop nip 5+ c@+ type ;THEN 5+ c@+ 1+ + u<
UNTIL 2drop r>
: `.w \ n -- ; pretty print n
dup -9 10 within IF .\ ;THEN ."$" $FF <= drop IF .b ;THEN .w
;
: `mr \ mod reg -- ; disassemble addressing mode and register
0 CASE 0 CASE ."PC" ;THEN 2 CASE ."@PC" ;THEN
`p@+ swap 2& drop IF `.w ."_#" ;THEN `p@ 2- + $FFFF& `.sym ."_$"
;THEN \ -- mod reg
2 CASE 0 CASE ."SR" ;THEN 1 CASE `p@+ `.sym ."_&" 1 `p +! ;THEN \ p odd:&&
1 swap << . ."#" \ 4 8
;THEN \ -- mod reg
3 CASE 3 = drop IF -1_ THEN . ."#" \ 0 1 2 -1
;THEN \ -- mod reg
over 1- 0= drop IF `p@+ `.w ."_(" THEN
over 2& drop IF ."@" THEN
1 CASE ."SP" ELSE ."R" 10 /% 0- drop IF ."1" THEN '0'+ emit THEN
1 CASE .")" ;THEN 3 CASE ."+" ;THEN drop
;
: `sop \ op -- ; disassemble single op
$1300 CASE ."RETI_" ;THEN
dup $1000 $1300 within 0= IF drop ."???_" ;THEN
dup $0380& 5 >> "RRC_SWPBRRA_SXT_PUSHCALL" drop + 4 `type \ -- op
dup $40& drop IF .".B" dup $80& drop IF ."??" THEN THEN space
dup 4 >> 3& \ -- op Adst
: `dstreg swap $F& `mr `p@ 1& IF ."&" THEN `p -! space \ `p odd:&&
;
: `emuop \ emulated instructions: {op[2],name[4]}*
[ $4130 w, ] ,"RET_" [ $4303 w, ] ,"NOP_" \ MOV@SP+,PC MOV#0,R3
[ $C312 w, ] ,"CLRC" [ $D312 w, ] ,"SETC" \ BIC#1,SR BIS#1,SR
[ $C322 w, ] ,"CLRZ" [ $D322 w, ] ,"SETZ" \ BIC#2,SR BIS#2,SR
[ $C222 w, ] ,"CLRN" [ $D222 w, ] ,"SETN" \ BIC#4,SR BIS#4,SR
[ $C232 w, ] ,"DINT" [ $D232 w, ] ,"EINT" \ BIC#8,SR BIS#8,SR
[ $4130 w, ] ,"POP_" [ $4300 w, ] ,"CLR_" \ MOV@SP+,rm MOV#0,rm
[ $5310 w, ] ,"INC_" [ $5320 w, ] ,"INCD" \ ADD#1,rm ADD#2,rm
[ $6300 w, ] ,"ADC_" [ $7300 w, ] ,"SBC_" \ ADDC#0,rm SUBC#0,rm
[ $8310 w, ] ,"DEC_" [ $8320 w, ] ,"DECD" \ SUB#1,rm SUB#2,rm
[ $9300 w, ] ,"TST_" [ $A300 w, ] ,"DADC" \ CMP#0,rm DADD#0,rm
[ $E330 w, ] ,"INV_" [ $4000 w, ] ,"BR__" \ XOR#-1,rm MOVx,PC
[ $5000 w, ] ,"RLA_" [ $6000 w, ] ,"RLC_" \ ADDr,r ADDCr,r
[ $5090 w, ] ,"RLA_" [ $6090 w, ] ,"RLC_" \ ADDm,m ADDCm,m
: `emu? \ key @ # -- @|0 ; z?=emu ; scan `emuop table, display name if emulated
TIMES w@+ >rswapr> = drop swap IF 4 `type 0 BREAK 4+ REPEAT nip 0-
;
: `RL 2 `p +! \ RLA RLC
: `BR space 4_ >> dup 4 >> swap 3& `dstreg ; \ BR
: `dop \ op -- ; disassemble double op
dup `emuop ' 10 `emu? 0= IF 2drop space ;THEN \ -- op @ ; 0op
BEGIN over $FF30& swap 11 `emu? \ -- op @ ; z?=emu ; 1op
WHILE over $F0CF& swap 1 `emu? `BR 0= ? \ -- op @ ; z?=emu ; BR
over dup 8 >> ^ $F& drop 0= \ src.reg==dst.reg ; nz?=regular ; RL
WHILE over $F0B0& swap 2 `emu? \ -- op @ ; z?=emu ; RLr
WHILE `p@ mem+ dupw@ swap 2+ w@ ^ drop 0= \ src.lit==dst.lit
WHILE over $F0B0& swap 2 `emu? `RL 0= ? \ -- op @ ; z?=emu, nz?=regular
END swap \ -- @ op ; z?=emu, nz?=regular
IF dup $4000- $F000& 10 >> \ -- @ op op.code*4
"MOV_ADD_ADDCSUBCSUB_CMP_DADDBIT_BIC_BIS_XOR_AND_" drop + 4 `type \ -- @ op
THEN dup $40& drop IF .".B" THEN space swap 0- drop \ -- op ; z?=emu
IF dup 4 >> 3& over 8 >> $F& `mr .",_" `p@ 1& `p -! \ Asrc src.reg
THEN dup 7 >> 1& `dstreg \ Ad dst.reg (`p odd:&&)
;
: .wop \ op -- ; disassemble op
dup $2000- drop 0< `sop ? \ singleOp, otherwise:
dup $4000- drop 0>= `dop ? \ doubleOp, otherwise conditional:
dup $3FF& swap 10 >> 7& 3* \ -- joff cond*3
"JNZJZ_JNCJC_JN_JGEJL_JMP" drop + 3 `type space \ -- joff
$200 >= drop IF $400- THEN 2* `p@ + `.w ."_$_"
;
variable `col stdout , \ display column to align comments
: `coltype \ @ # --
`col 4+ @ stdout- drop IF 2dup `col 4+ @ write drop THEN \ copy to file
2dup stdout write `col +! \ to display; reset `col for each LF(ASCII 10):
bounds BEGIN c@+ 10- drop 0= IF over over- `col! THEN u<= UNTIL 2drop
;
: @DIS` \ @ -- ; disassemble from address @
;` depth 0= drop IF wsparse find 0- drop IF !"???" ;THEN THEN `p!
`coltype ' type !^
BEGIN 0 `col! `p@ `p@+ .wop `p@ swap \ -- @end @start
23 `col@ - 0 max TIMES space REPEAT
."\\_" 2dup 2wdump swap - 2/ 3+ 5* TIMES space REPEAT
stopdump?
UNTIL type ^^
;
: TX2 dup TX 8 >> TX ; \ w -- ; LSByte1st,
: RX2 RX RX 8 << | ; \ -- w ; MSByte2nd.
dumpterm` ' alias DUMPTERM`
\ -------------------------------------------------------------------
[1] [IF] ."+_BSL43_-_MSP430_ROM-BootStrap-Loader^J"
\ BSL43 testing steps:
\ - comment([0]) this file's BLD43 and FLD43 sections
\ - check on a scope RST/DTR and TCK/RTS signals, and the BSLRST sequence
\ - check on a scope BSLTX and BSLRX: after BSLRST, send $80, must reply $90
\ - execute >MER to fully Mass-ERase the MSP flash
\ - execute >PASS to access the ROM bootstrap-loader
\ you may use BRST as a shortcut to execute: BSLRST >PASS
\ - play with ;BSLDUMP to check the flash is erased, or to dump the ROM
\ interactivity is limited by the ROM-BSL bug, which displays XXXX^=YYYY:
\ check that XXXX is off ram code and data (XXXX>=$0A00 is always safe)
\ - uncomment([1]) this file's BLD43 section and continue testing there.
0 constant [TRANSMISSION-LESS-TEST]`
[TRANSMISSION-LESS-TEST] [IF] \ fake RX/TX to see what would be transmitted:
: RX ."<90" $90 ;
: RX2 RX RX 8 << + ;
: TX .">" 2 .#s ;
: TX2 dup TX 8 >> TX ; \ for transmission-less test
0 constant BLDPORT 0 constant BSLPORT
[THEN]
\ PC.uart1.BSLPORT (i.e. "1 uart! BSLPORT port!") is used to communicate with
\ MSP430 ROM BootStrapLoader software UART on P1.1=BSLTX and P2.2=BSLRX
\ PC.uart0.BLDPORT (i.e. "0 uart! BLDPORT port!") is used to communicate with
\ MSP430 Flash BootLoaDer UART (see FLD43 chapter hereunder).
\ BSL/uart1@4800bpsEvenParity
\ BLD/uart0@115200bpsNoParity
\ RESETuart supports DTR and RTS signals, used for RESET and TCK:
[~] RESETuart [IF] 0 equ RESETuart [THEN] \ default: RST/TCK on uart0
[~] RST0 [IF] DTR1 ' alias RST0 DTR0 ' alias RST1 [THEN] \ inverted by V24
[~] TCK0 [IF] RTS1 ' alias TCK0 RTS0 ' alias TCK1 [THEN] \ inverted by V24
\ [Q1] F135 RST+BSL/uart1/DB9'0 BLD/uart0/DB9-25 (RST inverted by WD PCB)
\ [NC1] F135 RST+BLD/uart0/MSP.BRXBTX
\ [ATX] F147 RST+BLD/uart0/DB9'0/MSP.UART1 BSL/uart1/DB9'1
\ [ET] F147 RST+BSL/uart1/DB9'0 BLD/uart0/DB9'1/MSP.UART1
[os] [IF] [ELSE] $11 CommStateFlags! [THEN] \ 10DTRen+1Binary (see ff.ff)
[~] BLDPORT [IF] \ unless BLDPORT already defined:
[os] [IF] 0 [ELSE] 1 [THEN] constant BLDPORT \ Linux:ttyS0 Windows:COM1
[THEN]
[~] BSLPORT [IF] \ unless BSLPORT already defined:
[os] [IF] 32 [ELSE] 2 [THEN] constant BSLPORT \ Linux:ttyUSB0 Windows:COM2
[THEN]
0 uart! BLDPORT port! 1 uart! BSLPORT port! ;
: flushRX COM@ 1+ drop IF BEGIN RX? WHILE RX drop REPEAT THEN ;
: MSPRST \ -- ; boot-flash: while TCK high, RST low then high
\ RST xxx_______________--------------------- BSLTX=P1.1>
\ TCK xxx-------------------xxxxxxxxxxxxxxxxx BSLRX=P2.2<
\ ^ user program starts at address in $FFFE
COM 4+ @ 3& \ save current uart
[ RESETuart ] [IF] \ RESETuart=1:
1 uart! BSLPORT port! 4800 bps ' catch 0- drop
IF drop 0 uart! flushRX ."Please_reset_MSP..._"
ELSE evenParity flushRX
RST0 10 ms 0 uart! flushRX 1 uart! flushRX
RST1 20 ms ."MSP_reset,_"
THEN
[ELSE] \ RESETuart=0:
1 uart! BSLPORT port! 4800 bps ' catch 0- drop IF drop ELSE evenParity THEN
0 uart! COM@ 1+ drop IF ( keep bps ) 0 ELSE
BLDPORT port! 115200 bps ' catch THEN 0- drop
IF drop 1 uart! flushRX ."Please_reset_MSP..._"
ELSE noParity flushRX
RST0 10 ms 1 uart! flushRX 0 uart! flushRX
RST1 20 ms ."MSP_reset,_"
THEN
[THEN]
uart! \ restore current uart
;
: BSLRST \ -- ; boot-rom: RST low, 2 falling-edges on TCK, then RST high
\ RST xxx_______________--------------------- BSLTX=P1.1>
\ TCK xxx---____----______----_______________ BSLRX=P2.2<
\ TMS xxx---------------------_______________
\ 1^ 2^ ^ bootloader starts at $0C00
COM 4+ @ 3& \ save current uart
[ RESETuart ] \ this drives RESET low twice:
[IF] 1 uart! BSLPORT port! 4800 bps evenParity
[ELSE] 0 uart! BLDPORT port! 115200 bps noParity
[THEN] flushRX
RST0 2 TIMES TCK1 1 ms TCK0 1 ms REPEAT RST1 1 ms TCK1 20 ms
uart! flushRX \ restore current uart
;
: >PASS \ -- ; unlock protected BSL functions with key=FFE0+20(IntVect)
\ RXpassword >80>10>24>24>xx>xx>xx>xx>data00>data01...>data1F>CKL>CKH<ACK
"^@~^P$$____...:...|...:...|...:...|...:...|++"
over 8+ $FFE0 `@ swap $20 cmove $90
: BSLframe \ @ # cc -- ; >$80 ... >CKL>CKH<cc
\ Sync sequence before every command (provides timings): >80<90
$80 TX RX $90- drop IF !"NAK!" ;THEN 5 ms \ send synchro and check ACK
\ Checksum CKH.CKL such that xor of odd bytes = xor of even bytes = 0
>r 2dup 0 swap 2/ 1- TIMES swap w@+ rot ^ REPEAT \ -- n
\ ROMbug: BSL computes the same (in $212) at each byte (received in $206):
\ 0FB4: XOR.B $206 &, $212 (R9) XOR 1 #, R9 \ with R9=0/1 normally.
\ But when receiving the checksum two bytes, R9=n instead of R9=0/1:
\ 0D3C: and 0E02: MOV $212 &, R9 CALL $0F10 # MOV $206 &, $212 CALL$0F10#
\ This messes the two bytes at $212+n !!!
$212 over+ .w ."\^=" ~ dup .w space swap w! \ setup chksum
XSEND RX r> - drop IF !"unexpectedRX" THEN \ send and chek answer
;
: >BLK \ @ # -- ; RXdatablock >80>12>N>N>AL>AH>N-4>00>d0...>dN-4>CKL>CKH<ACK
\ This command works only for RAM, it's broken for flash (see BSLframe)
tuck 2dup 16 << | over 4+ $01010000* $1280+ \ -- # @ # AN NN
eob 8+ tuck! 4+ tuck! 4+ rot `@ -rot place 8- swap 10+ \ -- eob+8 #+10
$90 BSLframe
;
: <BLK \ @ # -- ; TXdatablock >80>14>04>04>AL>AH>N>00>CKL>CKH
2dup \ <80<xx<N<N<data1<data2...<dataN<CKL<CKH
16 << | "^@~^T^D^D____++" -rot tuck 4+ ! swap $80 BSLframe
RX RX2 2drop over `@ over XRECV RX2 drop bounds 2wdump
;
: >PC \ @ -- ; LoadPC >80>1A>04>04>AL>AH>xx>xx>CKL>CKH<ACK
"^@~^Z^D^D____++" >r over $1E84^ over 6+ w! tuck 4+ w! r> $90 BSLframe
;
: >PASSfixSP \ -- ;
\ BSL initializes SP anywhere between $21A and maxRAMaddress < $C00;
\ then >BLK may corrupt the return stack, or the last word loaded by >BLK
\ may be corrupted by the return stack, therefore setup SP=$21A is safer:
>PASS $0C22 >PC \ see ROM at $0C22: requires second >PASS
>PASS
;
: >MER \ -- ; MassErase >80>18>04>04>xx>xx>xx>xx>CKL>CKH <ACK
."Type_<Enter>_to_mass-erase,_or_any_other_key_to_cancel:"
key 13 = drop IF drop key THEN 10- drop IF !"Mass-erase_cancelled." ;THEN
0 "^@~^X^D^D__^D~^\++" SKIP \ such that chksm n=0
: >ERS \ @ -- ; EraseSegment >80>16>04>04>AL>AH>02>A5>CKL>CKH <ACK
"^@~^V^D^D__^B%~++" SKIP
: >ERI \ @ -- ; Ersmain|info >80>16>04>04>AL>AH>04>A5>CKL>CKH <ACK
"^@~^V^D^D__^D%~++" THEN THEN -rot tuck 4+ w! swap $90 BSLframe
;
: BRST` \ -- ; reset with current pass
;` 1 uart! 4800 bps evenParity BSLRST \ this drives RESET low a 3rd time.
:^ MERPASS \ -- ; mass-erase flash, and use virgin pass
>MER $FFE0 `@ $20 2dup eob 8+ place -rot 2dup $FF fill \ save&clear pass
>PASSfixSP cmove ; \ use&restore pass
>PASSfixSP ' MERPASS !^ \ default: use current pass (mass-erase: MERPASS ^^ ;)
: ;BSLDUMP` \ @ -- ; upload and dump memory from @ (while no ROMbug-mess)
;` BEGIN 16 2dup <BLK + stopdump? UNTIL drop
;
[THEN] \ BSL43
[0] [IF] \ ============================================================
: <ROM \ -- ; dump ROM into rom43.bin
BSLRST >PASS $0C00 $80 8 TIMES 2dup <BLK swap over+ swap REPEAT 2drop
"rom43.bin" openw ?ior $0C00 `@ $400 ior@ write ior@ close 2drop
;
: @ROM \ -- ; load rom43.bin into host memory image of MSP430
"rom43.bin" openr ?ior $0C00 `@ $400 ior@ read ior@ close 2drop
;
\ The following source generates the same binary code as rom43.bin:
\ ------------------------------------------------------------------
\ RAM allocation:
\ 200: bitPeriod in MCLK cycles ($80:-________--- S=D0-6=0,D7=P=S=1)
\ 202: bitPeriod/2 - 35 to sample in middle of bit
\ 204: TXbuf, 205: TXbitCounter
\ 206: RXbuf, 207: RXbitCounter
\ 208: .0=parityAcc .1=passMismatch .2=passOK
\ 20a: frame header: 0a:$80 0b:cmd 0c:size1,size2 0e:AL,AH 10:NL,NH
\ 212: cheksum
\ 214-21a: CALLstack(3 words), SPini=21a
\ ------------------------------------------------------------------
\ ROM start:
$0C00 org \ 0C00: 0C02 ROM reset vector
MOV $5A80 #, WDTCTL && \ 0C02: 40B2 5A80 0120
DINT \ 0C08: C232
\ setup SP
CMP $021A #, SP \ 0C0A: 9031 021A
JLO $0C22 $ \ 0C0E: 2809 if SP u< 21a (var),
CMP $0C02 #, SP \ 0C10: 9031 0C02
JHS $0C22 $ \ 0C14: 2C06 or SP u> C00 (ROM),
PUSH $A5B8 # \ 0C16: 1230 A5B8
POP R5 \ 0C1A: 4135
CMP $A5B8 #, R5 \ 0C1C: 9035 A5B8
JZ $0C26 $ \ 0C20: 2402 or SP not pointing in RAM,
MOV $021A #, SP \ 0C22: 4031 021A SP=21a
MOV.B $85 #, BCSCTL1 && \ 0C26: 40F2 0085 0057 BCSCTL1 = $85
MOV.B $80 #, DCOCTL && \ 0C2C: 40F2 0080 0056 DCOCTL = $80
BIS.B 2 #, P1OUT && \ 0C32: D3E2 0021 P1.1 = out
BIS.B 2 #, P1DIR && \ 0C36: D3E2 0022 P1.1 = 1
BIC.B 4 #, P2DIR && \ 0C3A: C2E2 002A P2.2 = in
CLR.B $0208 && \ 0C3E: 43C2 0208 208.B = 0
\ ------------------------------------------------------------------------
\ receive command: 2.
CALL $0E2A # \ 0C42: 12B0 0E2A 1. receive byte $80, reply ACK
CALL $0DBA # \ 0C46: 12B0 0DBA 2. receive frame header
MOV.B $020B &, R5 \ 0C4A: 4255 020B
CMP.B $12 #, R5 \ 0C4E: 9075 0012
JZ $0D06 $ \ 0C52: 2459 if 20b == $12 -> RXdatablock
CMP.B $10 #, R5 \ 0C54: 9075 0010
JZ $0CDA $ \ 0C58: 2440 if 20b == $10 -> RXpassword
CMP.B $18 #, R5 \ 0C5A: 9075 0018
JZ $0C9C $ \ 0C5E: 241E if 20b == $18 -> MassErase
CALL $0E02 # \ 0C60: 12B0 0E02 2. recv checksum
BIT.B 4 #, $0208 && \ 0C64: B2E2 0208
JZ $0C8E $ \ 0C68: 2412 1. if 208.2 == 0 -> reply NAK
MOV.B $020B &, R5 \ 0C6A: 4255 020B
CMP.B $16 #, R5 \ 0C6E: 9075 0016
JZ $0CAC $ \ 0C72: 241C if 20b == $16 -> ErasSegment
CMP.B $14 #, R5 \ 0C74: 9075 0014
JZ $0D76 $ \ 0C78: 247E if 20b == $14 -> TXdatablock
CMP.B $1A #, R5 \ 0C7A: 9075 001A
JZ $0C94 $ \ 0C7E: 240A if 20b == $1A -> LoadPC
CALL $0E84 # \ 0C80: 12B0 0E84 1. reply $70=unsupportedCommand
JMP $0C42 $ \ 0C84: 3FDE -> receive command
\ ------------------------------------------------------------------
\ reply ACK 1.
CALL $0E94 # \ 0C86: 12B0 0E94 1. reply ACK
JMP $0C42 $ \ 0C8A: 3FDB -> receive command
\ ------------------------------------------------------------------
\ pop caller and reply NAK
INCD SP \ 0C8C: 5321 SP += 2
\ ------------------------------------------------------------------
\ reply NAK 1.
CALL $0E8C # \ 0C8E: 12B0 0E8C 1. reply NAK
JMP $0C42 $ \ 0C92: 3FD7 -> receive command
\ ------------------------------------------------------------------
\ LoadPC 1. >80>1A>04>04>AL>AH>xx>xx>CKL>CKH<ACK
CALL $0E94 # \ 0C94: 12B0 0E94 1. reply ACK
BR $020E && \ 0C98: 4210 020E PC = *20e
\ ------------------------------------------------------------------
\ MassErase 2. >80>18>04>04>xx>xx>xx>xx>CKL>CKH <ACK
CALL $0E02 # \ 0C9C: 12B0 0E02 2. recv checksum
MOV $1000 #, $020E && \ 0CA0: 40B2 1000 020E 20e = $1000
MOV $A506 #, $0210 && \ 0CA6: 40B2 A506 0210 210 = $A506
\ ------------------------------------------------------------------
\ EraseSegment 1. >80>16>04>04>AL>AH>02>A5>CKL>CKH <ACK
BIT 1 #, FCTL3 && \ 0CAC: B392 012C
JNZ $0CAC $ \ 0CB0: 23FD wait FCTL3.0 == 0
MOV $A500 #, FCTL3 && \ 0CB2: 40B2 A500 012C FCTL3 = $A500
MOV $0210 &, FCTL1 && \ 0CB8: 4292 0210 0128 FCTL1 = *210