Needed to take a bit of a break after the 33 day streak. Spent a bit of time looking at the Forth word structure. Figured out .int was giving a 32 bit int instead of 16 bit. Think the alignment issues should be worked out now. Did some other testing with MSP430 Forth. Simplified the test case a bit by about 10-20 lines.
Played around with the minimal Forth I pulled out and think I've figure out why IP was going to 0. So I pulled in more words to have a closer to realistic test (QUIT, RZ, RSPSTORE, & BRANCH.)
Spent my time tonight ripping out everything but what was needed to test some things. Specifically it still had NEXT, DOCOL, main, a word, and an assembly code word. I believe I've tracked the problems I've been having to the way the instruction pointer is handled in the inner interpreter. I'll probably spend tomorrow diagramming out the memory & program flow. It's nice to have the problem narrowed down more. It's much less nice not knowing exactly how to solve said issue.
I spent a fair amount of time moving code out of the main (only) source file into smaller files. I first pulled the macros into a header, then I pulled groups of word definitions into separate files, and finally fixed compilation errors. I ended up needing to declare more labels as global. In addition to that, I also implemented the rest of the comparison operations, fixed some potential problems, and finished finished the implementation for another word. I think I'm down to the last 9 words to implement (and some have partial implementations.)
Went through and added TODO markers for all incomplete words. Made stubs for several subroutines. Implemented MUL & DIVMOD as well as untested >CFA & INTERPRET.
I think I mentioned this before, but the one thing I dislike about MSP430 assembly is the lack of multiplication & division mnenomics. That said, the naive multiply function is trivial:
/* Arguments are passed in r12 & r13, r15 is used to store the result */ clr r15 1: add r12, r15 /* ignores overflow */ dec r13 jnz 1b /* To comply with the MSP430 GCC calling convension, the result would be put back into r12 */
Division is a bit more complicated, but still didn't seem too bad. I'm not posting that because I haven't done any verification of it yet. This one at least had minimal testing in isolation.
Most of the time was working on an Ember.js application and really getting everything ready to go to fully start learning the framework. During this process I fixed a couple issues with pipeln's javascript loading via requires. One issue was it wasn't processing a file that was included with a require. However, require_tree seemed to be working as expected. Looking at the code, it ended up being pretty obvious that the processing wasn't being called there, but it was being called from the require tree function.
Once that was fixed, things started loading, but the javascript was then breaking on the client side. Turns out, another thing I sort of arbitrarily decided when writing the initial implementation of the asset loader was to collect all require statements, then go though each processing as required, and finally prepending them to the file.This can pretty easily cause errors with undefined variables after it's loaded into the browser. My solution was to include the files processed from require/require_tree statements at the site they're declared at. This way, if the require is at the bottom of the file, it loads the file at the bottom.
I also played around a little with Bourbon, Neat, & Bitters in so far as to give up on them for now since the Sass processing isn't built into pipeln yet. I briefly looked at options for building them outside of that. Manually compiling the Sass also only yielded about 200 lines of CSS with the imports for the three libraries. As that seemed like a mistake, I decided to table that for now and go with Bootstrap.
Earlier today I spent some time with MSP430 Forth cleaning up some things and committing some code that's been hanging out uncommitted for several days now.
Didn't get much done tonight. Found the msp430-elf-run command. Fixed some things when running it.
Keeping it short tonight since I've been terrible about sleeping a proper amount at night.
Shortly after posting last night, I remembered that I should be looking at the linker script for hints as to what it's expecting. Sure enough, up by the top there's something like:
__interrupt_vector_9 : { KEEP (*(__interrupt_vector_9 )) KEEP (*(__interrupt_vector_timer0_a1)) } > VECT9
So, of course I tested the human readable version
.macro SECTION_VECTOR vector .section __interrupt_vector_\vector,"ax",@progbits .endm .global test_int SECTION_VECTOR timer0_a1 .word test_int .text test_int: push r9 mov #9, r9 pop r9 reti
Compiled it and did an objdump -S:
Disassembly of section __interrupt_vector_9: 0000fff0 <__interrupt_vector_9>: fff0: 2e c1 interrupt service routine at 0xc12e 0000c12e <test_int>: c12e: 09 12 push r9 ; c130: 39 40 09 00 mov #9, r9 ; c134: 39 41 pop r9 ; c136: 00 13 reti
So there you have it. Mystery solved (or at least, was a mystery to me.) They were nice enough to allow a tolower version of the vector name appended to __interrupt_vector_ be used to lookup the expected name. This was much easier than the weird preprocessor macro expansion I was trying to get working last night.
I seem to be unable to find the documentation regarding interrupts (especially with regard to the generated assembly.) I decided to write a quick C test to figure out what it's expecting. It's interesting, but not surprising, the old toolchain and new toolchain produce interrupts differently.
#include <msp430.h> #define t_int(i) void __interrupt(i) test_##i() {} t_int(TRAPINT_VECTOR) t_int(PORT1_VECTOR) t_int(PORT2_VECTOR) t_int(ADC10_VECTOR) t_int(USCIAB0TX_VECTOR) t_int(USCIAB0RX_VECTOR) t_int(TIMER0_A1_VECTOR) t_int(TIMER0_A0_VECTOR) t_int(WDT_VECTOR) t_int(COMPARATORA_VECTOR) t_int(TIMER1_A1_VECTOR) t_int(TIMER1_A0_VECTOR) t_int(NMI_VECTOR) t_int(RESET_VECTOR)
compiled with:
msp430-elf-gcc -I$MSPGCC/include -mmcu=msp430g2553 -S test_inter.c
It results in (just a snippet):
.balign 2 .global test_TIMER0_A0_VECTOR .section __interrupt_vector_10,"ax",@progbits .word test_TIMER0_A0_VECTOR .text test_TIMER0_A0_VECTOR: ; start of function ; attributes: interrupt ; framesize_regs: 0 ; framesize_locals: 0 ; framesize_outgoing: 0 ; framesize: 0 ; elim ap -> fp 2 ; elim fp -> sp 0 ; saved regs:(none) ; start of prologue ; end of prologue ; start of epilogue RETI .size test_TIMER0_A0_VECTOR, .-test_TIMER0_A0_VECTOR
A similar macro
#define t_int(i) void __attribute__((interrupt(i))) test_##i() {}
for the old toolchain produced:
.p2align 1,0 .global test_TIMER0_A0_VECTOR .type test_TIMER0_A0_VECTOR,@function /*********************** * Interrupt Vector 9 Service Routine `test_TIMER0_A0_VECTOR' ***********************/ test_TIMER0_A0_VECTOR: .global __isr_9 __isr_9: push r4 mov r1, r4 add #2, r4 pop r4 reti .Lfe7: .size test_TIMER0_A0_VECTOR,.Lfe7-test_TIMER0_A0_VECTOR ;; End of function
It's interesting that the new toolchain puts the interrupt in a different section, while the old toolchain has a predefined global that, I'm assuming, the linker knows to look for. Not sure which one I like, but both feel relatively under documented.
Today is my 15th day in a row. I think I'm more proud of that than what I was able to accomplish today.
I didn't get nearly as much as I would have liked to done. I started reading the documentation for USCI UART in the User's Guide, I started to look at how MSPGCC generates interrupts in assembly. At about that time, I realized I'm not yet using the upstream Ti MSP430 GCC. I ended up downloading that, and fixing my code to compile with that toolchain, which was trivially adding a couple ampersands in front of some constants. It was actually more work to edit the Makefile to work out the MSP430 GCC toolchain directory. I find it slightly inconvenient to need to tell msp430-elf-gcc where to include standard headers from. Overall, I think the new toolchain is the right switch going forward.
Only had about 15 minutes today. Spent it looking at msp430-forth and started implementing KEY when I ran out of time. Maybe I'll have more time tomorrow.
Implemented around 9 more words for this Forth implementation. Again, I mostly focused on easy words, but that's about the last day I can do that. The rest are a bit more complicated, but are the last bits for really getting a working Forth. The other outstanding piece is serial output so things like TELL, EMIT, & KEY can be implemented.
It was getting kind of late, and I decided to go back to my MSP430 port of jonesforth that I've been on for awhile now. I implement a few more words, improved readability of the defvar & defconst statements, and fixed a potential issue with alignment. I have about 20 words left to implement of the assembly before I can start really testing it. Really, it's getting about to the point where I'll have to implement a basic serial interface for interaction. I'm currently at 2602 bytes, still well within the MSP430G2553's 16K of storage. However, I'm clearly above some of the smaller chips, like the MSP430G2211 which was one of the original chips to ship with the Launchpad. I'm not sure how much I really care to target those devices.
I'm going to cheat a little because I didn't get home from work until about 20 minutes ago. This is a place-holder until I have a bit of time to write about something. I'll likely be doing a bit of MSP430 assembly again tonight since I have my MSP-EXPFR5969's firmware up-to-date now.
Ok, I really did end up doing a bit of MSP430 assembly. Energia on Linux was still complaining about the programmer firmware still being out of date, so I went through and more thoroughly tried updating it. I then went back and started stepping through my attempted port of JonesForth to the MSP430.
This is an MSP430 assembly reimplementation of my day #1. One of the things that I really like about the MSP430 instruction set is that there are 52 instructions & 7 addressing modes. Because of this, I think the assembly tends to be very easy to follow. I did, however, get a bit lazy when writing this. The 6 local labels likely make this code a bit odd to read (especially without looking at the equivalent C code.) It's about 10 bytes larger than the C code compiled with -O
While simple, this was my first try at getting physical sound output with a microcontroller (MSP430 Launchpad) and an 8Ω speaker. This does a basic sweep-like sound (going from high to low.) This was a quick recreation of what I did last night since I only had 3 hours to submit for today and am still at work. However, the basic concept is still instilled in this code.