YAP – Yet Another Programmer

So back in the PWM-ADC project I mentioned that I could not get my interrupts to work, assumed that it must be the stupid silicon (and not ME), and went off to program a different part. Well, I discovered that my ancient PICStart programmer would not program a 16f877a. Apparently the firmware was too old. Looking at upgrading the PICStart I decided that that would amount to beating a dead horse. So I decided that I could breadboard a programmer. (In the end, my breadboard programmer did program the ‘f887a, I burned my program that failed on the ‘f876, and I got the same results on both PICs! Debugged the code and discovered I was not handling interrupts correctly. Let that be a lesson to you.) So I’m left with a programmer project to finish. But I have reservations about it.

The cons are:

  • Time consuming development project.
  • There are lots of programmers out there.
  • A useful result will require a packaged (PCB, case, cables) product.
  • Can it provide more value than existing programming options?

The pros are:

  • It can support any devices I desire.
  • It will not depend upon any vendors development system.
  • It can be made to resolve any bootloader issues.
  • Extra functionality like debugging, JTAG, SPI/I2C would be possible.
  • It will be linux plug-and-play.

Since the PWM-ADC project my PICStart had died. I’ve been using my new PICkit3 to good effect. The only real hassle there is providing the 6-pin connector on each breadboard. So, as far as PICs go, I don’t really need a stand-alone programmer. But the up-coming Rotary Encoder project is going to be done on a breadboarded Arduino platform. It will require “extras” to connect to AVRDude. I do not want to have to have those extras on each Atmel powered project that I do. So a dedicated off-line programmer may be a very useful device. And even considering PICs, I think there may be issues down the road where more advanced parts that are only supported by vendor tools beyond the PICkit3. A stand-alone programmer might allow one to avoid those problems. So I think that, in the long run, a programmer may be a useful project. Besides, I’ve already programmed a 16f877a, so I have content for my WEB page.

Proof-of-Concept

There are some caveats that go along with this project. Proof-of-concept implies that, initially, we are just going to do the minimal possible to demonstrate to ourselves that we can program a specific part (16f877a). Code at the host and code at the programmer will not have things like error checking, a fantastic user interface, freedom from communications lock-ups, etc. Automation of some functionality will come later. There is a Tkinter GUI interface. Let me say something about that. I used Tkinter because it is part of every python distribution. Linux, Windows, and Mac will all have Tkinter. If you use Idle for python development on your system you have to realize that Idle uses Tkinter (at least it did when I tried it long ago). If you try to open the programmer GUI there will be a conflict. You have to write special start-up code to get a separate programmer GUI. I always used Python for Windows Extensions. There will be no GUI issues. Of course, if you program in a text editor and launch from a terminal window like a sane person, all these issues go away.

Speaking of the GUI, Tkinter will probably be superceded by wxWidgets. This is because wxWidgets has a more capable editor window than Tkinter. So plan on Tkinter going away.

Another issue is that of the serial communications. I am using pySerial for the RS-232 functionality. That will have to be installed separately. I probably could have used native python library functions, but I was too lazy to learn them. And, hopefully, the RS-232 will be replaced by USB, but that will not happen for a while.

Finally, progress on this project will be sporadic. Other projects will be published and only from time to time will another page and video be added here. No schedule. If any of these issues are a show-stopper for you, you have been warned.

Programmer Functionality

We will need two sets of software for the programmer: the PIC firmware and the User Interface. The original PIC was programmed in assembler. Since then I’ve obtained a 18f2550 (more memory and a USB interface) and re-wrote the code in C. The user interface is written in python. Python is available for MS, linux, and Mac.

We need to off-load as much work as possible from the ‘f2550 by doing a bunch of preprocessing on the host. First there is the .hex file. We’re not just going to transmit a .hex file to the PIC programmer. We will turn the .hex file into a byte stream of machine code only. We need to devise a communication protocol. Basic command/response handshaking between host and PIC will enable us to transmit data and cause specific actions at the programmer and target.

Host User Interface

I‘ll start with the python host software first. It’s the best place to show how the data to be transmitted is generated, how command/response communications will operate, and how the user will interface with the system.

Data Generation

The host requires an Intel HEX formatted file. There are 6 parts to each line of the file:

  • Start Code
  • Byte Count
  • Address
  • Record Type
  • Data Field
  • Checksum

:10000000172800000000000083168C1E142883129D

Each line of the file is referred to as a “record”. Evey record starts with the Start Code, “:”. Every other character on the line is an ASCII hexadecimal character, and each pair of those characters represents a single, 8-bit, hexadecimal value (byte). Therefore, the actual number of “bytes” represented by a record is one half the number of ASCII characters.

The Byte Count is the number of bytes in the Data Field. Address is 4 hex characters that are the 16-bit starting address of the data in this record. Record Type is 2 hex digits that indicate the type of data in the data field. The Data Field may contain 0 to 16 “bytes” (0 to 32 ascii characters) for the Record Type that we will be using (see host code discussion in video). The Checksum is calculated over all characters in the record excluding the “:”.

The Data Field contains the machine code to be programmed into the target and requires the greatest amount of processing. First, hexadecimal values will be created by combining each pair of ASCII characters. These hex values are machine bytes. The Mid-Range PIC instructions are 14-bit machine words. Therefore, we will need to assemble each machine byte from 2 ASCII characters, and each machine word from 2 machine bytes. Now we can see that from one 16-byte data record we can form 8 PIC instruction words. The Mid-Range PICs are little-endian format. This means that instruction stored in memory are in the order of MSB/LSB, That seems natural enough. However, Intel processors are big-endian format which means that they store instructions in memory as LSB/MSB. Therefore, Intel hex files are big-endian also. So additionally we have to swap each pair of hex bytes from the record to form the PIC instruction word.

The CRC is calculated for each record by accumulating the sum of each pair of ASCII characters converted to their integer value. Then the ones-compliment value is generated ((SUM xor 0xff) + 1) and truncated to a byte value. The CRC will be calculated and checked against the CRC at the end of each record. The start code is not part of the CRC calculation.

Usage of the remainder of the data fields is fairly straigntforward. Data length field is compared to the extracted field length, the address field is tracked against a running address calculation, and the record type is used to confirm a data record or an end-of-file record. More details are found in the comments in the user interface software.

Communications

Tcurrent code supports a 240 byte limit on the size of the transmitted program data (due to the original use of the ‘f876 in this application). The ‘f2550 has much more memory but data will still have to be sent in chunks for most programs. To keep the computing load as small as possible on the PIC, we need to supply a variety of data in addition to the program code:

  • Starting address – PIC does not have to track addresses.
  • Data length – PIC stores this value for use during program data reception.
  • Program Data – PIC stores “data-length” bytes in memory, computing s CRC.
  • Request CRC – PIC has computed a CRC on received data & returns that CRC.
  • Program Command – PIC burns the target with current data.
  • Request Status – PIC returns state of RS-232 error flags & other status.

A simple, synchronous, protocol is devised where a single byte, representing a command, is sent to the PIC. I have arbitrarialy used hex values starting at 0x11 and continuing through 0x1d. The command is then followed by zero or more data bytes, as appropriate to the command. Upon receiving the command plus any data, the PIC responds with an acknowledgement (ACK: Ox06) or a negative acknowledgement (NAK: 0x15). A typical sequence of commands would be:

   HOST     <<===>>      PIC
   0x1a (chip erase)     ACK
   0x11 (set address)    ACK
   0x12 (set data len)   ACK
   0x13 (send program)   ACK
   0x14 (request CRC)    CRC
   0x15 (program target) ACK

See the code listings for full description of command structure and for the full functionality of the GUI.

GUI

I‘m not a big fan of GUIs at all. My preference is to use them for applications that have graphical content or a lot of multi-mode outputs and inputs i.e. tables, statuses, option selections, etc.. I’m using one here, however, because my hope is that this programmer function will grow into an application with lots of multi-mode I/O. So I’m including a GUI right away to avoid any major code rewrites.

Currently, the GUI only has raidio buttons to select actions, a file selector for the .hex file, and a status line. Scattered through the code are print statements that dump debugging information to the terminal.

PIC Programmer Firmware

Serial communications are handled by enabling the serial port and the serial receiver interrupt. Interrupt service reads the byte from RCREG, places it in RxByte, and sets the DAV bit in STATE.

The main loop, starting at idle:, watches the DAV bit in STATE for a “1” and calls the decode_command( ) function. decode_command( ) uses a switch statement to match RxByte and call the appropriate function. Six commands are implemented in this current version. Each command is responded to with an ACK byte sent to the host. This synchronous communication removes the need for any flow control signals in hardware or software. Currently, the best description of the code may be had by reading the comments in the C file. More functionality will be added as the project continues.

To itemize the limitations on the code:

  • Does not try to program target, but acknowledges that it did. (stub)
  • Will not handle any address changes. Only starts programming at 0000,
  • Only handles 240 byte data chunks
  • Only Data and End-of-File records are serviced
  • No functionality beyond the communication between host and programmer

Unless you find the communications interesting or you are just curious, there may not be much of interest in the code yet.

Download Programmer Project: python Host and C PIC code: programmer-0-1.zip

NOTE: I’m not providing tar files as WordPress (rather, Windows, no doubt) does not understand file extensions for compressed tars. Zip files can be handled by everyone.



©copyright 2015 pretzelogic LLC. All rights reserved.
No part of this page may be reproduced without permission.
Software, schematics, and text are presented as reference works only.
No claim as to useability, suitability, or correctness for any application is made.