My Mac OS X development tool chain for PIC is now complete. I successfully assembled my Ifos project (and by extension, my Modbus and Framework projects) on the Mac using GPUTILS, then programmed it over ICSP using pp and a K150 programmer. This was not a painless process.
I have a perfectly good K150 USB programmer I’ve used for a couple of years, and the MicroPro software that came with it is full-featured and fast. Unfortunately, it’s also PC-only and closed-source. Google turned up a few potential substitutes:
A few others popped up, but these four generated the most board buzz. I tried them all.
#1 failed with “Data too large for PIC ROM”, no matter how small the hex file I used.
#2 transferred the data, but always failed to verify the ROM afterward (which, not surprisingly, never worked).
#3 always produced an infinite beach ball, requiring a forced quit.
#4 simply hung.
Ok, a not-so-great start. QProg was particularly disappointing since it was the only one specifically targeted to the Mac AND it forced me to install 180MB of Qt framework before its epic fail.
tetsujin’s script seemed well-written, but my Python is pretty thin, so I wasn’t too keen on wading in and trying to debug it (although in retrospect, it would have been a good opportunity to improve my Python skills, and the interactive shell would have made debugging pretty easy). Instead I started looking at pp.
I dropped in a few printf() calls and found pp would hang when trying to access the serial port. When I looked at the code, it was clear why: the open() call would block until carrier was detected—common enough with “real” serial devices like modems, but my USB-to-Serial cable would never simulate it. The general solution is to open in non-blocking mode (just to obtain a file handle, we can reset the non-blocking flag later), then disable the modem controls with the CLOCAL flag (see §3.6 of the Unix Programming FAQ). Relevant lines:
From serial.c:
fd = open( port, O_RDWR | O_NOCTTY | O_NDELAY ); fcntl( fd, F_SETFL, fcntl( fd, F_GETFL, 0 ) & ~O_NONBLOCK );
With the above changes in place, I was able to successfully clear my PIC18F242 over ICSP. Cool, but will it program?
Evidently not. I can live with the misspelling, but the segmentation fault is a little more problematic.
Long story short, pp had a bunch of problems I had to resolve before I could get anywhere. The INHX32 parser, in particular, had several serious errors, mostly due (probably) to a lack of need/opportunity to use it with any 16-bit PICs. Here’s a quick run-down of the problems I found:
0x03ff, rather than chip-specific value (this also caused image length calculation to fail)I’m not actually complaining about these problems, mind you. The original author of pp made it clear that it was an early release, and I’m just happy he sat down and cranked out the code. Fixing a few bugs was a lot less work than writing the whole thing from scratch. I’m just listing the issues here in case anyone else runs into trouble with pp and 16-bit PIC chips. Evidently there used to be an SVN repository off the main project page, but I wasn’t able to access it, either to check for these fixes in later versions or contribute my own changes1.
With fixes in place for all the known issues, pp was operating perfectly. Well, except for the fact that nothing I programmed actually worked on the PIC. Out came more printf() calls (what data exactly was being written to which memory exactly?), and sure enough, the fuses always came back blank—even though I had explicitly inserted the correct P018 command. What gives?
First of all, I ran a simple test program (everyone loves blinky) through my old PC-based tool chain, just to ensure I had a working hex file. I assembled and linked, then programmed the PIC all from the PC with no problems— blinky lived up to its name. Next I took that hex file and programmed it from the Mac using pp. No joy.
Returning to the PC, I used USB Snoopy (what a life-saver!) to watch the interaction between the K150 and MicroPro, then compared that to the behavior of pp. I found two very interesting items:
0x11) (re)sent the block of fuse data.I had a couple of theories about #1. They might be for timing purposes. They might be some undocumented hand-shake necessary for normal operation. They might be simple, “Are you still there?” queries at logical checkpoints. Of these, the last seemed most likely. As for #2, the observed behavior was definitely at odds with the published specification, which clearly asserted no fuse data was to be sent with command 0x11.
I went ahead and modified pp to match the behavior of MicroPro and lo and behold, blinky started working whether it was programmed from the PC or the Mac.
Programming from the Mac was working, but building on the Mac was still untested, so the next step was to produce blinky using GPUTILS there. Unfortunately, the resulting binary would not run on the device. Drat.
A quick comparison of the hex output from both tools showed two major differences. First, the instruction offsets did not match, leading me to discover that the linker files provided with GPUTILS differed from those included with MPLAB (at least for the PIC18F242). The default version included a dedicated area for “vectors” in low memory, so I copied it to the GPUTILS file and rebuilt. blinky remained DOA, however, which wasn’t totally unexpected.
The second difference was a little more unsettling. For some reason, MPLAB inserted a nop instruction just ahead of the retfie in the ISR. Hmmm… Ok. Time to check all errata sheets for the chip… Nope, nothing there. Ok, well—let’s put it in and see what happens.
That did it. It seems to imply that retfie must be long-word-aligned, but I can’t find any documentation to that effect. Here are the original binaries, for comparison (as disassembled by gpdasm).
|
Generated by gpasm:
000000: 6af2 clrf 0xf2, 0
000002: ef16 goto 0x0e 000004: f000 000008: ef15 goto 0x0c 00000a: f000 00000c: 0011 retfie 0x1 00000e: 6a8b clrf 0x8b, 0 000010: 6a94 clrf 0x94, 0 000012: 8282 bsf 0x82, 0x1, 0 000014: 9482 bcf 0x82, 0x2, 0 000016: 0e16 movlw 0x16 000018: 6e00 movwf 0, 0 00001a: 0e74 movlw 0x74 00001c: 6e01 movwf 0x1, 0 00001e: 0e06 movlw 0x6 000020: 6e02 movwf 0x2, 0 000022: 2e00 decfsz 0, 0x1, 0 000024: d007 bra 0x34 000026: 2e01 decfsz 0x1, 0x1, 0 000028: d005 bra 0x34 00002a: 2e02 decfsz 0x2, 0x1, 0 00002c: d003 bra 0x34 00002e: 7282 btg 0x82, 0x1, 0 000030: 7482 btg 0x82, 0x2, 0 000032: d7f1 bra 0x16 000034: d7f6 bra 0x22 60000000: 22ff addwfc 0xff, 0x1, 0 60000002: 0e0d movlw 0xd 60000004: 01ff movlb 0xff 60000006: ff81 dw 0xff81 ;unknown opcode 60000008: c00f movff 0xf, 0xf 6000000a: e00f 6000000c: 400f rrncf 0xf, 0, 0 |
Generated by MPLAB:
000000: 6af2 clrf 0xf2, 0
000002: ef16 goto 0x2e 000004: f000 000008: ef15 goto 0x2c 00000a: f000 00002a: 0000 nop 00002c: 0011 retfie 0x1 00002e: 6a8b clrf 0x8b, 0 000030: 6a94 clrf 0x94, 0 000032: 8282 bsf 0x82, 0x1, 0 000034: 9482 bcf 0x82, 0x2, 0 000036: 0e16 movlw 0x16 000038: 6e00 movwf 0, 0 00003a: 0e74 movlw 0x74 00003c: 6e01 movwf 0x1, 0 00003e: 0e06 movlw 0x6 000040: 6e02 movwf 0x2, 0 000042: 2e00 decfsz 0, 0x1, 0 000044: d007 bra 0x54 000046: 2e01 decfsz 0x1, 0x1, 0 000048: d005 bra 0x54 00004a: 2e02 decfsz 0x2, 0x1, 0 00004c: d003 bra 0x54 00004e: 7282 btg 0x82, 0x1, 0 000050: 7482 btg 0x82, 0x2, 0 000052: d7f1 bra 0x36 000054: d7f6 bra 0x42 60000000: 22ff addwfc 0xff, 0x1, 0 60000002: 0e0d movlw 0xd 60000004: 01ff movlb 0xff 60000006: ff81 dw 0xff81 ;unknown opcode 60000008: c00f movff 0xf, 0xf 6000000a: e00f 6000000c: 400f rrncf 0xf, 0, 0 |
So finally, after many hours debugging other people’s code, sniffing USB data packets, and examining disassembly files, I have a working PIC development tool-chain on the Mac. Hooray! I did have to incorporate the mysterious nop instruction into Ifos, but that appears to be the only change required. GPUTILS is working great, and pp is working. That’s all I need!
1 Unpack pp-0.1.tar.gz, move to the directory created, then patch -b -p1 < pp.patch (attached).
| Attachment | Size |
|---|---|
| pp.patch | 21.48 KB |
Comments
Source update: I went ahead
Source update: I went ahead and created a project on GitHub to track my version of the pp tool. You can find it at http://github.com/pheinrich/PIC-pp and get a copy using something like: