Introduction
This blog post looks at a very small microcontroller board called the StartUSB for PIC StartUSB for PIC, and shows how it can be used either as a standalone microcontroller board or used to control your own hardware (either off-board or built on the supplied prototyping area) via USB control from a PC.
A condensed summary steps version of this post in PDF format is available here.
A brief history
Many hobbyists are familiar with microcontrollers from Atmel on a credit-card sized board and a turquoise software development environment known simply as Arduino.
A microcontroller is a “computer-on-a-chip”; usually it contains the central processing unit (CPU) and program and data memory all-in-one. It is available in tiny sizes sometimes with less than a dozen pins that can be used to control and interact with the outside world.
In the early 1990’s two firms that delivered microcontrollers that largely competed in the same space became popular with hobbyists; one was Atmel and the other was a company called Microchip. Their microcontrollers were relatively simple chips available in friendly low-pin-count DIP packages and the programming tools were reasonably low cost and affordable by individuals.
Most of these early devices had very little memory and software was written in assembler language; as a result of the investment in getting up-to-speed, developers for the Microchip range tended to stick with the Microchip products (known as PIC microcontrollers) and the developers for the Atmel range (known as AVR microcontrollers) stuck with those.
The situation is very different now; the increased memory and better instruction sets means that often development is done in the (slightly) higher-level C language and therefore it is far easier for programmers to rapidly swap between different processing architectures. The introduction of Flash memory that can be programmed at low voltages has reduced the cost barrier of modern in-circuit programming tools and often (not always) the compilers are free.
During those hobbyist PIC/AVR wars I ended up trying some of the PIC12 range, and rapidly moved to the Atmel products as soon as Flash memory in microcontrollers because popular. The PIC12 range had a particularly simplistic instruction set that made it very tedious to write assembler code; I was far more comfortable with Intel, Motorola and Hitachi microcontrollers at that time. The Motorola 68HC11 series and the Hitachi H8 series in particular had easy-to-use instruction sets and they could be self-programmed without requiring any programming hardware.
What is a Bootloader?
The process to self-program involves relying on a simpler program to load the main program into memory.
Often this means setting a pin just before power-up which puts the microcontroller into a mode where it sits and waits for characters to arrive on its asynchronous serial interface (usually wired using RS232 to a PC) and put them into internal RAM. A small program called a ‘bootloader’ was written and sent via the RS232 interface from the PC into the microcontroller. With clever programming the bootloader would then execute from RAM and then receive the main program and automatically self-program the microcontroller’s internal Flash memory.
Modern microcontrollers now support USB bootloader capability either as supplied from the manufacturer or initially programmed in to a portion of the Flash memory using an in-circuit programming tool. The StartUSB board has such a bootloader (described in detail later). The process to work with this board involves writing and compiling code in the usual manner and then sending the built .hex output file via a PC tool called mikroBootloader (available for download here) to the StartUSB board which will already have a bootloader pre-installed in a portion of Flash memory.
8-Bit Popularity
Nowadays although 8-bit microcontrollers are still available, 32-bit device popularity has been increasing. This year is probably the last year when 8-bit microcontroller revenue might exceed 32-bit revenue for microcontroller manufacturers.
Manufacturers like Atmel (recently acquired by Dialog Semiconductor) and Microchip are still launching 8-bit products since 8-bit parts continue to be popular. Texas Instruments, Renesas, Silicon Labs and Freescale still produce 8-bit microcontrollers too – often at under $1 price.
What is the StartUSB for PIC?
The MikroElektronika ‘StartUSB for PIC’ is a very compact board with a PIC 18F series microcontroller on-board with 32Kbyte Flash, 2kbyte SRAM and 256 byte EEPROM. The main board could probably fit inside a small box of matches if the prototyping areas are snapped off (there are scored lines to break it off).
I was interested in this board ever since the Dreamboard Vs Battle because the StripBoard++ dream-board had intended to have a prototyping area built-in too.
I had not used PIC devices in an extremely long time so it would be interesting to revisit them. I wanted to come to it with an open mind; I don’t use many Atmel AVR nor Microchip PIC devices these days.
It was disappointing that a few things had not changed at all – the official programming tool PICkit 3PICkit 3 is slightly pricier than the Atmel tool, and the Microchip compiler (called XC8) is a chargeable product (the free version produces larger, slower code).
Nevertheless, these may be small barriers for commercial customers if the benefits and cost of PIC microcontrollers are greater than the competition. Commercial customers will be willing to pay the cost of the tools and compiler.
It was also noticed that a potential low-cost entry to PIC microcontroller development boards is the new Microchip Curiosity board. I decided to plough ahead with the StartUSB board and document how I used it.
Advantages of the StartUSB for PIC board
The StartUSB for PIC board is fairly low cost (but certainly not the cheapest if we’re comparing microcontroller dev boards) and is very compact yet retains the ability to be able to connect up SIL header pins (these are supplied unsoldered). I also like that it has a small prototyping area for building additional circuits.
The StartUSB board does not need a programmer; it can be programmed using a USB connection to a PC because it comes with a bootloader pre-programmed into a portion of Flash memory.
The features inside the microcontroller (the full part code is PIC18F2550) are reasonable-to-pretty-good for a 28-pin device. The CPU runs at a fairly speedy 48MHz, and there is built-in USB device functionality capable of connecting at up to USB ‘Full Speed’ mode (12Mbps) to a USB host such as a PC. It also contains serial interface features including UART, SPI and I2C, and a 10-bit analog-to-digital converter (ADC) and three 16-bit timers and an 8-bit timer, a comparator and dual PWM (10-bit) capability. It is a good set of functionality for a small 8-bit device.
What are the Disadvantages?
The board is primarily designed to work with a 5V USB connected supply; although the supply pins are broken out to the SIL header pins, there is no protection if the USB supply is connected at the same time. This is something to be aware of (it won’t impact all use-cases).
Another disadvantage is that there is no hardware programmer on the board; instead the PIC 18F microcontroller is pre-programmed with the bootloader which is designed to wait five seconds whenever it is plugged into a USB port to see if the host device (e.g. PC) wants to transfer across a new program (using PC software supplied by MikroElektronika known as ‘mikroBootloader’ or ‘USB HID Bootloader’ tool) into Flash memory (taking care not to overwrite the PIC 18F bootloader which also resides in Flash memory). After the 5-second delay the bootloader assumes the user does not intend to upload a new program and starts up any exiting program in Flash.
The procedure works fine, but does mean that there is a 5-second delay before program execution at power-on.
There is also the risk that the user may accidentally wipe the bootloader and then the startUSB board is useless until the bootloader can be reprogrammed into it (using a separately purchased PIC programmer). This is disappointing but again is more relevant to the new hobbyist than a commercial customer. Those already using PIC devices will likely already have a PIC programmer so this becomes a non-issue for them.
Installing the Development Environment
Microchip’s integrated development environment (IDE) is called MPLAB X and it was installed as well as their compiler toolchain known as XC8. MPLAB X looks much like any other IDE and was fairly easy to get into. I used the Windows version but Linux and Mac is available too. Much like any other IDE, there is a set of logically grouped files on the left that are part of the project, and the main code view is where all the work is done. In brief the 'hammer' icons are used to build the code into a final .hex file and the entire process is logged into the 'Output' pane at the bottom.
Deciphering the Bootloader
What was very disappointing to see was that the bootloader isn’t documented by MikroElektronica at all. Without such documentation it is difficult to build software for the StartUSB because the user has no idea which areas of Flash memory to avoid.
If MikroElektronika’s compiler is used (it is known as MikroCMikroC) then presumably all is fine; it should happily build code targeted for the StartUSB board. However, I wanted to use Microchip’s MPLAB X and XC8, and I didn't have MikroC. Besides, some customers may already have invested in XC8 and may not want to purchase another compiler.
A small bit of reverse-engineering of the bootloader (a copy of the hex file was supplied in the zip file containing the PC software mikroBootloader) was needed. MPLAB X has the capability to disassemble code by importing in the hex file and running it using an internal debugger and bringing up a ‘PIC Memory View’ window.
It soon revealed that the bootloader resides at the top portion of memory and that the PC software that connects to the bootloader automatically moves the reset vector so that the bootloader can call the user’s program after the 5-second timeout. The diagram below shows the disassembly at the reset vector (in blue) and the bootloader (in green). The table on the right shows the 20 or so bytes of bootloader disassembly. So, it is expected for the user program to sit anywhere in the On-Chip Program Memory as shown on the diagram, as long as it doesn’t trample the bootloader. The bootloader uses a specific location (shown in red) for the user program jump vector. Click on the image below to see all this in detail.
All that was needed to do was to avoid overwriting the bootloader. This was easy; in the MPLAB X IDE, right-click on the project and select ‘Properties’. In the Project Properties window that appears, select ‘XC8 linker’ and then option category ‘Memory model’. The ‘ROM ranges’ parameter which by default is blank needs to be set to :
default,-653c-7fff
The steps above will ensure that the memory from address 0x653c to 0x7fff is avoided. These are the locations used by the bootloader present in the StartUSB board. When the program is transferred by using the MikroElektronica supplied PC software called mikroBootloader, the PC software will automatically map the reset vector in the user program hex file into the correct location to serve as the program jump vector for the bootloader to use.
Hello World
Another irritating issue is that the StartUSB has no supplied source code for an example user application; by default the board comes with pre-compiled code in the Flash memory which flashes two LEDs. Without the source code to that, a user has to fly solo for their first program.
Still, it is resolvable; I wrote my own demo which approximates the pre-compiled demo program. It is shown here but the source code is attached so use that; no need to copy-and-paste.
/**************************************************** * Description: StartUSB for PIC demo program * for MPLABX with XC8 * (Alternately flashes two LEDs) * File: main.c * Author: shabaz * Revision: 1.0 - 24th October 2015, First Version ****************************************************/ // include files #include <p18f2550.h> #include <xc.h> // pragmas' // See XC8 install folder \docs\chips\18f2550.htm for these values: #pragma config PLLDIV=2 // 8MHz crystal, divided by 2 #pragma config USBDIV=2 // USB clock is 96MHz/2 = 48MHz #pragma config CPUDIV=OSC1_PLL2 // CPU clock is 96MHz/2 = 48MHz #pragma config FOSC = HSPLL_HS // CPU is clocked from HS_PLL path #pragma config FCMEN = OFF // Fail-safe clock monitor enable is off #pragma config BORV = 3 // brown-out voltage level (3 is minimum) #pragma config WDT = OFF // Watchdog is off #pragma config CPB=OFF, CPD=OFF // Code protection bits are off // definitions #define LED_RED LATAbits.LATA1 #define LED_GREEN LATBbits.LATB1 // global variables unsigned int subtick=0; // used in the ISR unsigned int msec=0; // counts 0-999 repeatedly unsigned int sec=0; // counts upward forever unsigned char sec_toggle=0; // toggles every second unsigned char msec100_toggle=0; // toggles every 100msec unsigned int msec100; // counts upward forever // function prototypes void msec100_tick(void); void sec_tick(void); // interrupt service routine void interrupt low_priority LowIsr(void) { if(PIE1bits.TMR2IE && PIR1bits.TMR2IF) { subtick++; if (subtick>=3) { subtick=0; msec++; if ((msec%100)==0) { msec100++; msec100_toggle^=1; msec100_tick(); } if (msec>=1000) { msec=0; sec++; sec_toggle^=1; sec_tick(); } } PIR1bits.TMR2IF=0; // reset interrupt flag } } void msec100_tick(void) { if (msec100_toggle) { LED_RED=0; LED_GREEN=1; } else { LED_RED=1; LED_GREEN=0; } } void sec_tick(void) { } void init(void) { T2CON=0x07; // timer 2 on, speed=48MHz/2/16 = 750kHz PIR1bits.TMR2IF=0; // clear timer 2 interrupt flag PR2=250; // timer 2 compare match value PIE1bits.TMR2IE=1; // enable timer 2 interrupt (on compare match) INTCONbits.PEIE=1; // peripheral interrupt enable RCONbits.IPEN=1; // enable priority levels system IPR1bits.TMR2IP=0; // set timer 2 interrupt to be low priority INTCONbits.GIE=1; // enable global interrupts TRISAbits.RA1=0; // set port A bit 1 as an output TRISBbits.RB1=0; // set port B bit 1 as an output } // main function int main(void) { init(); while(1) { // loop } return(0); // ignore warnings on this line }
The code can be compiled up and transferred to the StartUSB board using the mikroBootloader PC tool. When the board is reset, after a 5 second delay the bootloader will run the code and it will flash two LEDs rapidly repeatedly.
Doing More Useful Things: USB
I was particularly interested in getting USB to work for user programs, so that this board could become a useful go-to device for quick and low-cost integration of hardware projects with PCs. The PIC18F2550 is not supported by the automatic code generation tools that Microchip offers for more recent processors so I had to resort to trying to compile code from Microchip’s Library for Applications (MLA) which is a set of source code for useful libraries. After some (brutal) messing around the USB finally worked – the code I tested used the USB Human Interface Device (HID) class which usually doesn’t need any driver installing on the PC. The HID class is typically used by keyboards and mice which would be inconvenient to use if they required a driver for basic functionality each time they were plugged into a new PC. The HID class can also be used for generic data transfer bi-directionally and this is what was of interest to me.
To perform bidirectional transfer some example PC host side software is supplied as part of the MLA code both in compiled and source code form – various demo code exists for all platforms. I only tried a pre-built Windows application for now, which successfully allowed me to toggle a pin on the PIC microcontroller from the Windows application and to receive the status of a different pin; this proved that communication in both directions is possible.
The code on the PIC microcontroller sits and waits for a packet from the USB host (e.g. PC) and then checks to see if it is a command to toggle an LED, or to send data with the status of another pin. It should be easy to modify this to do more advanced things.
The code is attached to the post. If you wish to modify it, you can see where the code for the LED and button press and high-level USB packet handling for them resides here in a file called app_device_custom_hid.c:
The command definitions are in that same file. The LED and buttons are defined in a file called io_mapping.h and the actual low-level port input/output for them occurs in files called led.c and buttons.c respectively – nice and simple!
Summary
I’m excited to see that the PIC 18F devices have vastly more functionality than the early PICs of yesterday.
Nevertheless it would be a nice gesture for Microchip to release a no-support (e.g. community edition) of their full XC8 compiler with no restrictions but we can assume this will not occur.
This was just a short review; I certainly will re-visit PIC devices and as mentioned the PIC 18F could well become a popular part for me for general microcontroller use where I may want USB and other basic bits of functionality and not have to redo effort. The 28-pin SOIC and DIP availability of the microcontroller is handy.
The MikroElektronika StartUSB for PICMikroElektronika StartUSB for PIC is an interesting board; it has the fairly decent PIC microcontroller on-board and the board itself is a great form-factor with the proto-board area alongside that can be optionally removed.
However I wasn’t happy at the lack of public documentation. MikroElektronika is a reputable company with a vast portfolio of useful boards – a huge click range for instance; they should have just published the information and let users decide to use what vendor compiler is best for them.
Still, with the information above and the example code that was written, it should be possible for anyone to use this board with the MPLAB X environment and XC8 compiler.
I’m not sure the StartUSB for PIC board is best value though; if you need a small PIC board then it is fine, but otherwise I suspect (although I’ve not used it; it may have its fair share of advantages and disadvantages too) that the Microchip Curiosity board could be a better option because has a reduced set of PICkit functionality on-board so it doesn’t require a bootloader in Flash like the StartUSB for PIC board. But the compact size of the StartUSB for PIC board is very cool!
The source code mentioned in this post is attached below.
Top Comments