3 WHAT IS FAST FORTH FOR MSP430FR ?
5 FAST FORTH IS IT AN IDE ?
6 HOW TO MIX ASSEMBLY and FORTH ?
8 ASSEMBLY WITHOUT LABEL ?
9 SYMBOLIC ASSEMBLER ? YES !
11 Case of MSP430FR2xxx family (with FLL)
14 WHAT IS FAST FORTH FOR MSP430FRxxxx ?
17 FAST FORTH is a FORTH program written in MSP430 assembly and it runs on TI's LAUNCHPAD :
18 MSP-EXP430FR5739, MSP-EXP430FR5969, MSP-EXP430FR6989... or any MSP430 FRAM device.
20 Built-in assembler allows you to program an application using interruptions and LPMX modes.
26 a TI launchpad, I prefer MSP-EXP430FR5969
28 an UARTtoUSB cable with a PL2303TA device (preferred device) :
30 RX and TX wires are 3.3V level.
32 BE CAREFULL ! if you plan to supply your MSP430FRxxxx device with the PL2303TA cable,
33 you MUST open it to weld the red wire (+) onto the 3.3V pad !!!
37 or UARTtoUSB bridge with CP2102 device :
38 search on ebay :"UART to USB CP2102"
39 verify the presence of a 3.3V pin before buy !
42 If you want to test RC5toLCD.f :
44 a standard LCD DISPLAY 2x16 or 2x20 chars,
45 a VISHAY IR receiver TSOP32236 or equivalent plus an IR remote with RC5/RC6 Philips protocol,
46 a piece of PCB to wire the diode, resistor and two capacitors of the LCD_Vo booster.
48 And to use the SD_Card extension :
50 http://www.ebay.com/itm/2-PCS-SD-Card-Module-Slot-Socket-Reader-For-Arduino-MCU-/181211954262?pt=LH_DefaultDomain_0&hash=item2a3112fc56
52 http://fr.aliexpress.com/item/Reading-and-writing-SD-Card-Module-Slot-Socket-Reader-For-Arduino-ARM-MCU-free-Shipping/32351128089.html?spm=2114.06010108.3.314.T5C4eQ&ws_ab_test=201407_5,201444_5,201409_3
54 http://fr.aliexpress.com/item/5V-3-3V-Compatible-Perfect-SD-Card-Module-Slot-Socket-Reader-For-ARM-MCU-Read/32223868267.html?isOrigTitle=true
58 If you have MSP-EXP430FR994 launchpad, simply put a FAT16 formatted card in slot.
60 I suggest you to wire constantly the RX0 TX0 pins of your LAUNCHPAD (RX1 TX1 pins for MSP-EXP430FR6989 launchpad) to a free USB socket on your PC via the cable UARTtoUSB PL2303TA.
61 So you can drag and drop HEX file on MSP-EXP430FRxxxxprog.bat to regenerate FORTH kernel or download RC5toLCD.f without doing anything else...
64 FAST FORTH IS IT AN IDE ?
67 YES, if you admit that you can program in FORTH / in assembler, not C... Look at "RC5toLCD.f".
69 In fact, you have an IDE with two languages, one low level other high level, and it's easy to mix them.
72 HOW TO MIX assembly and FORTH ?
75 FAST FORTH knows two kinds of words :
77 low level assembly words start with CODE <name> and end with ENDCODE.
79 high level FORTH words begin with : <name> and end with ;
84 CODE ADD \ Assembly word, alias of word +
90 : NOOP \ FORTH word, do nothing
97 To end a low level assembly word, the instruction MOV @IP+,PC jumps to the next FORTH word. This faster (4 cycles) and shorter (one word) instruction replaces the famous pair of assembly instructions : CALL #LABEL ... RET (4+4 cycles, 2+1 words). The register IP is the Interpretative Pointer.
99 High level FORTH word starts with a boot code (13 cycles) that save the IP pointer, load it with the first address of a list of execution addresses, then perform a postincrement branch to this first address. The list ends with the address of another piece of code EXIT (6 cycles) that restores IP before the instruction MOV @IP+,PC.
102 here, the compilation of low level word ADD :
104 preamble \ compiled by the word CODE
105 execution addr ADD @PSP+,TOS
106 MOV @IP+,PC \ instruction called NEXT
108 and the one of the high level word NOOP :
110 preamble \ compiled by the word :
111 execution addr PUSH IP \ boot code compiled by the word :
112 CALL rEXIT \ boot code compiled by the word :
113 addr of DUP \ execution addr of DUP
114 addr of DROP \ execution addr of DROP
115 addr of EXIT \ execution addr of EXIT compiled by the word ;
118 _A high level FORTH word is a list of execution addresses preceded by a boot code and ending with EXIT address._
124 any low level FORTH words must be ended with the instruction MOV @IP+,PC (NEXT).
126 CODE TEST \ CODE starts a low level word
127 asm1 \ assembly instruction 1
128 asm2 \ assembly instruction 2
130 ENDCODE \ end of low level word
133 If you want to use the IP register, save it before and restore it before NEXT
135 CODE TEST1 \ CODE starts a low level word
136 asm1 \ assembly instructions
138 PUSH IP \ save IP before use
139 MOV #1,IP \ assembly instruction that uses IP
140 ... \ assembly instructions
141 MOV @RSP+,IP \ restore IP
143 ENDCODE \ end of low level word
146 A little more complex, the case of mixing FORTH and assembly
148 : MIX_FORTH_ASM \ definition of a FORTH word starts with :
151 HI2LO \ FORTH to assembler switch
152 asm1 \ assembly instruction
153 asm2 \ assembly instruction
154 ... \ you can freely use IP !
155 ... \ assembly instructions
156 MOV @RSP+,IP \ restore IP
158 ENDCODE \ end of low level word
160 If we see the code "MIX\_FORTH\_ASM" after compilation :
162 preamble \ compiled by :
163 exec@ PUSH IP \ compiled by : save IP
164 CALL rEXIT \ compiled by : and execute EXIT
165 addr \ execution addr of SWAP
166 addr \ execution addr of DUP
167 next addr \ addr of asm1, compiled by HI2LO
168 asm1 \ assembly instruction
169 asm2 \ assembly instruction
170 ... \ you can freely use IP !
171 ... \ assembly instructions
172 MOV @RSP+,IP \ restore IP saved by :
175 the instruction "CALL rEXIT" (CALL R7), have EXIT address as rEXIT content.
178 going a step further :
180 CODE MIX_ASM_FORTH \ CODE starts a low level word
181 asm1 \ assembly instruction 1
182 asm2 \ assembly instruction 2
183 COLON \ starts high level
186 ; \ end of high level word
189 If we see this code "MIX\_ASM\_FORTH" after compilation :
191 preamble \ compiled by CODE
192 exec@ asm1 \ assembly instruction 1
193 asm2 \ assembly instruction 2
194 PUSH IP \ compiled by COLON, save IP
195 CALL rEXIT \ compiled by COLON, CALL EXIT
198 addr of EXIT \ the word ; compiles EXIT that restores IP then executes MOV @IP+,PC
203 the first time, at the start of FORTH word, after save IP:
205 EXIT MOV @RSP+,IP \ 2 pop into IP next PC pushed on return stack by CALL rEXIT
206 MOV @IP+,PC \ 4 execute the routine pointed by the the address next "CALL rEXIT"
208 then at the end of FORTH word :
210 EXIT MOV @RSP+,IP \ 2 pop old IP from return stack
211 MOV @IP+,PC \ 4 execute the routine pointed by the old IP
216 : MIX_FORTH_ASM_FORTH \ definition of a FORTH word starts with :
220 HI2LO \ FORTH to assembler switch
221 MOV #0,IP \ IP is free for use
224 LO2HI \ assembler to FORTH switch
227 ; \ end of high level word
232 preamble \ compiled by :
233 exec@ PUSH IP \ compiled by : save IP
234 CALL rEXIT \ compiled by : and move next PC from return stack into IP
238 next addr \ compiled by HI2LO
239 MOV #0,IP \ IP is free for use
240 asm1 \ assembly instruction
242 CALL rEXIT \ compiled by LO2HI (10 cycles switch)
249 CODE MIX_ASM_FORTH_ASM \ CODE starts a low level word
250 asm1 \ assembly instruction
251 asm2 \ assembly instruction
252 COLON \ starts high level
255 HI2LO \ FORTH to assembler switch
256 asm3 \ assembly instruction
257 asm4 \ assembly instruction
258 MOV @RSP+,IP \ restore IP
260 ENDCODE \ end of low level word
262 In fact, with FASTFORTH, the start of a word FORTH can be placed anywhere :
264 CODE MIX_ASM_FORTH_ASM_FORTH
268 COLON \ starts high level
272 HI2LO \ FORTH to assembler switch
276 LO2HI \ assembler to FORTH switch
280 ; \ end of high level word
282 with the compiled result :
284 preamble \ compiled by CODE
287 PUSH IP \ compiled by COLON
288 CALL rEXIT \ compiled by COLON
291 next address \ compiled by HI2LO
294 CALL rEXIT \ compiled by LO2HI
297 EXIT addr \ that restores IP from return stack and then executes MOV @IP+,PC
299 As we see, IP is saved only once, it's logical.
302 ASSEMBLY WITHOUT LABEL ?
305 Yes ! the assembly syntax borrows FORTH's one for jumps :
308 CMP #1,R8 \ set Z,N,V, flags
309 0= IF \ irritating, the "IF =" upside down, isn't it?
310 ADD R8,R9 \ true part of comparaison
313 MOV @IP+,PC \ don't forget...
314 ENDCODE \ don't forget...
316 and the complete version :
318 CODE TEST_IF_ELSE_THEN
319 CMP #1,R8 \ set Z,N,V, flags
321 ADD R8,R9 \ true part of comparaison
323 SUB R8,R9 \ false part of comparaison
325 ... \ following for the two branches
326 MOV @IP+,PC \ don't forget...
327 ENDCODE \ don't forget...
329 test for loop back version BEGIN ... UNTIL
331 CODE TEST_BEGIN_UNTIL
334 SUB #1,R10 \ set Z,N,V flags
335 0= UNTIL \ loop back to BEGIN if flag Z is set
340 test for out of loop version BEGIN ... WHILE ... REPEAT
342 CODE TEST_BEGIN_WHILE_REPEAT
345 SUB #1,R10 \ set Z,N,V flags
346 0<> WHILE \ go to out of loop if X=0 (Z flag =1)
348 REPEAT \ unconditionnal loop back to BEGIN
349 ... \ out of loop here
355 CODE TEST_BEGIN_AGAIN
358 AGAIN \ unconditionnal loop back to BEGIN
361 to quit this infinite loop, press <reset>
363 We can nest several conditional branches :
365 CODE TEST_NESTED_IF_ELSE
382 CODE TEST_NESTED_BEGIN_AGAIN_IF
387 MOV @IP+,PC \ out of test_NESTED_BEGIN_AGAIN_IF
394 you can also MIX conditional branches with a mix of FORTH/assembly :
396 see TEST5 in the demo file \MSP430-FORTH\TESTASM.4TH
402 unconditionnal backward jump :
407 JMP TEST \ jump backward to the word TEST
410 conditionnal backward jump :
415 S< ?JMP TEST \ jump backward to TEST if negative
420 FAST FORTH have one pass assembler, not able to make forward jump.
422 In my (well written) apps I have never used forward jumps.
424 I have added possibility of several "non canonical" jumps, up to 3 backward and up to 3 forward imbricated jumps to label :
426 \ C UM/MOD udlo|udhi u1 -- ur uq
428 MOV @PSP+,W \ 2 W = DIVIDENDhi
429 MOV @PSP,S \ 2 S = DIVIDENDlo
430 \ T.I. ROUTINE Section 5.1.5 of MSP430 Family Application Reports
431 MOV #0,Y \ 1 CLEAR RESULT
432 MOV #16,X \ 2 INITIALIZE LOOP COUNTER
434 U< ?GOTO FW1 \ 2 if not carry
435 SUB TOS,W \ 1 if carry DIVIDENDhi-divisor
436 FW1 \ FW1 label is resolved therefore reusable
437 BW2 ADDC Y,Y \ 1 RLC quotient
438 U>= ?GOTO FW1 \ 2 if carry Error: result > 16 bits
439 SUB #1,X \ 1 Decrement loop counter
440 <0 ?GOTO FW2 \ 2 if 0< terminate w/o error
441 ADD S,S \ 1 RLA DIVIDENDlo
442 ADDC W,W \ 1 RLC DIVIDENDhi
443 U< ?GOTO BW1 \ 2 if not carry 14~ loop
444 SUB TOS,W \ 1 if carry DIVIDENDhi-divisor
446 GOTO BW2 \ 2 14~ loop
447 FW2 BIC #1,SR \ 1 CLRC No error, C = 0
448 FW1 \ Error indication in C
449 \ END T.I. ROUTINE Section 5.1.5 of MSP430 Family Application Reports
450 MOV W,0(PSP) \ 3 remainder on stack
451 MOV Y,TOS \ 1 quotient in TOS
456 SYMBOLIC ASSEMBLER ? YES !
459 I have discovered a little semantic preprocessor "GEMA",
460 just like that FAST FORTH have its symbolic assembler !
462 \config\gema\MSP430FR_FastForth.pat contains variables FORTH for all devices
463 \config\gema\MSP430FR57xx.pat contains declarations for FR57 family
464 \config\gema\MSP430FR5x6x.pat ... for FR59/FR69 families
465 \config\gema\MSP430FR2x4x.pat ... for FR2/FR4 families.
466 \config\gema\DEVICE.pat contains memory map and vectors for a specified DEVICE
467 \MSP430-FORTH\LAUNCHPAD.pat is the I/O config file for specific LAUNCHPAD or application
469 gema translates also FORTH registers in ASM registers (R0 to R15)
471 If you have created a network drive from your local gitlab directory, it's easy :
472 with scite editor open a file.f, then select in the menu "tools" the items "preprocess..."
474 furnished examples : see \MSP430-FORTH\
477 Try SD\_TESTS.f to build a SD\_Card test.
483 How to start your project ?
485 First you create two files : project.f and test.f
489 ; ----------------------------------------------------
490 ; MSP430FR5969 MSP_EXP430FR5969 8MHZ 921600bds PROJECT
491 ; ----------------------------------------------------
492 WIPE \ restore the content of FastForth.hex file
494 here you write your already tested routines :
514 then finish with two master words : START and STOP
516 CODE START \ to init your app
522 \ NOECHO \ uncomment if your app runs without terminal
523 LIT RECURSE IS WARM \ inserts START (so init app) in the FORTH init process
524 (WARM) \ then start app by continuing the FORTH init process
528 CODE STOP \ to stop app and interrupts if any
530 MOV #(WARM),2(R8) \ unlink START from FORTH init process
531 MOV #COLD,PC \ reset CPU that resets interrupt vectors
536 : STOP \ to stop app and interrupts if any
537 ['] (WARM) IS WARM \ remove START from FORTH init process
538 COLD \ reset CPU that resets interrupt vectors
543 RST_HERE ; thus allowing to restart your app with <reset> or COLD !
549 Each time you download this project file in LAUNCHPAD, the word WIPE returns the dictionary set as it was in HEX file. And the word RST_HERE protects the PROJECT against <RESET\>.
551 The word START allows to include app init into FORTH's one.
552 The word STOP unlink app.
554 Look at the file RC5toLCD.f to retrieve this structure.
560 \ ----------------------------------
561 \ MSP-EXP430FR5969_8MHZ_TEST.f
562 \ ----------------------------------
563 RST_STATE \ restore the state defined by PROJECT.f
565 here you write your routine to test
567 PWR_HERE \ test.f content is protected against POWER OFF, but volatile with <reset>
571 Each time you download this test file, the word RST\_STATE returns the <RESET\> dictionary set (i.e. PROJECT). The word PWR\_HERE protects the test against POWER OFF. without the word PWR\_HERE, the test is lost when power down.
576 With the TERATERM menu : send a file..., you download first your project.f file, then your test.f file that include the routine to test.
578 If the test don't work, modify it in the test.f file, then reload it.
580 When the routine "test" works as you want, you cut it in test.f file and copy it in project.f, then when you reload it, test is done !
586 Case of MSP430FR2xxx family (with FLL)
590 Difficult to donwload CORETEST.4th on CHIPSTICK @ 8MHz without error (tested with USBtoUART device = CP2102).
592 To resolve, I was forced to speed the clock up to 8.29 MHz ! (see ChipStick_fr2433.inc)
594 And there is no this problem @ 16MHz !
596 Is a problem that affects this device only ?
598 If you ever encounter the same difficulty, recompile + download CORETEST.4th several times by increasing each time by 2 the FLLN value until you reach the good compromising...
599 ...or use a MSP430FR5xxx device !
605 The embedded assembler don't recognize the (useless) TI's symbolic addressing mode: ADD.B EDE,TONI.
607 REGISTERS correspondence
609 ASM TI FASTFORTH comment
611 R0 PC PC Program Counter
612 R1 SP RSP Return Stack Pointer
613 R2 SR/CG1 SR Status Register/Constant Generator 1
614 R3 CG2 Constant Generator 2
615 R4 R4 rDODOES contents address of xdodoes
616 R5 R5 rDOCON contents address of xdocon
617 R6 R6 rDOVAR contents address of RFROM
618 R7 R7 rEXIT contents address of EXIT
619 R8 R8 Y scratch register
620 R9 R9 X scratch register
621 R10 R10 W scratch register
622 R11 R11 T scratch register
623 R12 R12 S scratch register
624 R13 R13 IP Interpretation Pointer
625 R14 R14 TOS Top Of parameters Stack
626 R15 R15 PSP Parameters Stack Pointer
628 FASTFORTH registers must be preprocessed by gema.exe before sending to the embedded assembler.
629 (don't use R3 and use R2 only with register addressing mode).
633 The FASTFORTH registers rDOCOL, rDOVAR, rDOCON and rDODOES must be preserved.
634 PUSHM R7,R4 before use and POPM R4,R7 after.
636 Under interrupt, the use of scratch registers and IP is free.
637 Else, only scratch registers.
642 The register TOS (Top Of Stack) is the first cell of the Parameters stack.
643 The register PSP (Parameters Stack Pointer) points the second cell.
645 to push one cell on the PSP stack :
647 SUB #2,PSP \ insert a empty 2th cell
648 MOV TOS,0(PSP) \ mov first cell in this empty 2th cell
649 MOV <what you want>,TOS \ or MOV.B <what you want>,TOS ; i.e. in first cell
652 to pop one cell from the PSP stack :
654 MOV @PSP+,TOS \ first cell is lost
660 register RSP is the Return Stack Pointer (SP).
662 to push one cell on the RSP stack :
664 PUSH <what you want> \
667 to pop one cell from the RSP stack :
669 MOV @RSP+,<where you want> \
672 to push multiple registers on the RSP stack :
677 to pop multiple registers from the RSP stack :
682 CPUx instructions PUSHM / POPM (my own syntax, not the TI's one, too bad :-)
684 PUSHM order : PSP,TOS, IP, S, T, W, X, Y, R7, R6, R5, R4
686 example : PUSHM IP,Y \ push IP, S, T, W, X, Y registers onto the stack RSP
689 POPM order : R4, R5, R6, R7, Y, X, W, T, S, IP,TOS,PSP
691 example : POPM Y,IP \ pop Y, X, W, T, S, IP registers from the stack RSP
693 error occurs if bad order (PUSHM Y,IP for example)
696 CPUx instructions RRCM,RRAM,RLAM,RRUM
698 example : RRUM #3,R9 \ R9 register is Unsigned Right shifted by n=3
700 error occurs if 1 > n > 4