Author: Stephen Ierodiaconou

April 15, 2016

I am currently working on Mangrove Root's very own smartdesk for our office. The smartdesk is an initiative started by Opendesk.

Having been an electronics hobbyist in the past I have amassed a large collection of components and, while the temptation is to simply buy a few more Arduino boards and shields, in the spirit of waste minimisation and reuse I am trying to repurpose some of these existing components into my smartdesk. I happen to have a pair of Microchip PIC18F4550 microcontrollers and wish to use them, so first point of call is setting up a development environment for these devices.

Programming language, compiler and simulator

Microchip provide a development environment (Mplab X) based on Eclipse. It includes an assembler, C compiler and a simulator. This would be an obvious choice, however I also wanted to explore the possibility of using open source tools instead. In terms of programming language for developing for the micro I wanted to find something slightly higher level than the PIC assembly language, preferably a C-like language (or C itself) but anything else with good support, and importantly, easy of use and rapid development.

My research led me to the following:

  • gpsim describes itself as "a full-featured software simulator for Microchip PIC microcontrollers distributed under the GNU General Public License, <...>. gpsim has been designed to be as accurate as possible."
  • JAL (Just Another Language) described itself as "JAL (Just Another Language, version 2) is an open source programming language built for programming PIC microcontrollers. If electronics is your thing, JAL is for you!"
  • jallib is a collection of open source libraries in JAL for PIC micros. Including libraries of code to use the various peripheral hardware these micros provide. It also includes definition files for all the PIC micro family.

I ended up not choosing to use C, primarily because experimenting with JAL appealed to me, however SDCC would have been the primary choice for compiler and IDEs and other tools for C abound (only problem is I understand the SDCC's support for 16 bit architecture PICs is still in development, but usable).

Compiling JALv2 for Mac OS X

Out of the box the source code for the JALv2 compiler (at time of writing version 2.4q5) will not compile with on Mac OS X (in my particular case using the XCode development tools I have Apple LLVM version 7.3.0).

Luckily some simple and probably very unorthodox tweaks (hacks!) we can get it into a working state (however no guarantees on how well it will work!). The following assumes you have wget, if not either download the source archive manually or install wget with homebrew:

$ mkdir ~/jal; cd ~/jal
$ wget http://www.casadeyork.com/jalv2/archive/jalv24q5src.zip
$ unzip jalv24q5src.zip
$ make
(...)
cod_file.c:954:10: error: cast from 'unsigned char *' to 'unsigned short *' increases required alignment from 1 to 2 [-Werror,-Wcast-align]
        *(ushort *) (base + COD_table_endpoints[ii].map_start_offset) = block;
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(...)
pic.c:2662:11: error: variable 'stack_depth' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
      if (!sz) {
          ^~~
(...)
jal_proc.c:1132:23: error: expression which evaluates to zero treated as a null pointer constant of type 'variable_def_t' (aka 'struct variable_def_ *')
      [-Werror,-Wnon-literal-null-conversion]
                      VARIABLE_DEF_TYPE_NONE);
                      ^~~~~~~~~~~~~~~~~~~~~~
(...)

The errors are mostly escalated warnings.

The 2 changes we need to make are to relax some errors back to warnings and to fix a pointer type cast to avoid setting a null pointer.

These patches include the required changes; first is Makefile.inc.patch:

--- Makefile.inc    2013-08-30 19:11:47.000000000 +0100
+++ Makefile.inc    2016-04-15 14:48:49.000000000 +0100
@@ -16,7 +16,7 @@
 #COVERAGE=-fprofile-arcs -ftest-coverage
 #PROFILE=-pg
 DEBUG=-g
-CFLAGS=-O0 -Werror -ansi -pedantic -W -Wall -Wshadow -Wcast-qual -Wcast-align $(DEBUG) $(PROFILE) $(COVERAGE)
+CFLAGS=-O0 -ansi -pedantic -W -Wall -Wshadow -Wcast-qual $(DEBUG) $(PROFILE) $(COVERAGE)
 LFLAGS=$(DEBUG) $(PROFILE) $(COVERAGE) -lm
 OBJ_DIR=.obj

And second is jal_proc.c.patch:

--- ../jalv24q5/src/jal/jal_proc.c  2013-05-26 18:10:15.000000000 +0100
+++ jal/jal_proc.c  2016-04-15 14:50:34.000000000 +0100
@@ -1129,7 +1129,7 @@
                   ct_val = pfile_value_find(pf, PFILE_LOG_NONE, ct_name);
                   if (!ct_val) {
                     ct_val = pfile_constant_get(pf, value_ct_get(val),
-                      VARIABLE_DEF_TYPE_NONE);
+                      VARIABLE_DEF_NONE);
                   }
                   parms[ii - 1] = ct_val;
                   FREE(ct_name);

Now if we apply the patches and compile again (note we need to make a 'bin' directory for the output binary):

$ mkdir jalv24q5/bin
$ cd jalv24q5/src
$ patch < Makefile.inc.patch
$ patch < jal_proc.c.patch
$ make
$ cd ../; bin/jalv2

jal jalv24q5 (compiled Apr 15 2016)

jallib and sample JAL

We will definitely be needing and reusing code from jallib. For the purpose of this setup we will also be using one of the sample JAL applications for the 18F4550 which simply 'blinks a LED' (simply toggles the value of a single bit on PORTA of the PIC):

$ cd ~/jal
$ git clone git@github.com:jallib/jallib.git
$ cp jallib/sample/18f4550_blink_hs.jal sample.jal

Here is the body of the short example (JAL uses a Pascal like syntax):

(...)
enable_digital_io()
alias led is pin_A0
pin_A0_direction = OUTPUT
forever loop
   led = ON
   delay_100ms(1)
   led = OFF
   delay_100ms(4)
end loop

Compiling the JAL sample

$ cd ~/jal
$ jalv224q5/bin/jalv2 sample.jal -s jallib/include/device/ -s jallib/include/jal/

Notice we must point JAL (using the -s option) at the location of the includes used in the example code. These includes are part of the large 'standard library' that jallib provides us with.

By default the JAL compiler will produce all of the following outputs next to the original .jal source file:

  • .asm: The resulting MPASM dialect assembly code for the PIC. If you open the this you will see that the compiler also emits the original JAL code as source comments.This is very useful to understand the mapping when debugging.
  • .hex: The compiled machine code in the Microchip Hex format. This site states it is "an extended Intel Hex file with code, data, configuration bytes and user ID included"
  • .cod: The compiled machine code in a Byte Craft Limited COD format (or symbol format). This is not a particularly open format.

Running the example PIC 18F4550 program

Using gpsim we can run and test the PIC machine code generated by JALv2.

Installation with homebrew is simple:

$ brew install gpsim

This will install gpsim CLI tools only (as the UI depends on GTK). The command line tool is easy enough to use an the build in help is invaluable

$ gpsim

gpsim - the GNUPIC simulator
version: Release 0.28.1

type help for help
**gpsim> help load
load [processortype] programfile
(...)

First we will load our Hex format output from compilation and then step through and watch the state of bit 0 of PORTA:

$ gpsim -ppic18f4550 sample.hex
SetProcessorByType FIXME

P18F4550 does not support USB registers and functionality

Extended linear address 0 0
Extended linear address 0 180000
CLKO not simulated
Disabling WDT
Leaving pic_processor::LoadProgramFile
**gpsim>

The output gives us some information about what gpsim can't do (shame about the USB functionality lacking) but also shows us that the watch dog timer has been disabled, as per our application configuration.

By referring to the .asm output we can see what to expect when we start stepping through the application in the simulator (disable the watch dog and set the the primary oscillator configuration):

bcf      v_wdtcon, 0,v__access
movlw    252
andwf    v_osccon,f,v__access

Sure enough when we start to step :

**gpsim> step
0x0000000000000000 p18f4550 0x0000 0x90D1 bcf    wdtcon,0,0
  Wrote: 0x00FF to t0con(0x0FD5) was 0x00FF
  Wrote: 0x0000 to wdtcon(0x0FD1) was 0x0000
**gpsim> step
0x0000000000000001 p18f4550 0x0002 0x0EFC movlw    0xfc
  Wrote: 0x00FC to W(0x0FE8) was 0x0000
**gpsim> step
0x0000000000000002 p18f4550 0x0004 0x16D3 andwf    osccon,f,0
  Read: 0x0040 from osccon(0x0FD3)
  Read: 0x00FC from W(0x0FE8)
  Wrote: 0x0040 to osccon(0x0FD3) was 0x0040
  Wrote: 0x0000 to status(0x0FD8) was 0x0000

If we now step ahead to the point at which we set the pin on PORT A high:

**gpsim> step 10
0x000000000000000C p18f4550 0x0062 0x8089 bsf    lata,0,0
  Wrote: 0x0001 to lata(0x0F89) was 0x0000

we can now find the symbol that equates to PORTA and check its value (should be 1):

**gpsim> symbol
Symbol table
(...)
porta0                    Type: IO_bi_directional
(...)
p18f4550.porta            Type: PicPortRegister
(...)
**gpsim> symbol p18f4550.porta
porta = 0x1
**gpsim> symbol porta0
 stimulus
 Vth=5V Zth=150 ohms Cth=0F nodeVoltage= 0V
 Driving=1 drivingState=1 drivenState=0 bitState=0

Note that the simulator actually provides us with both a simulation of the register for PORTA and the actual I/O pin state. The register is 1 as expected and the 0-bit pin of the port is driving a 1 value (5V).


Contact Us


Contact us to discuss your requirements!

We are always happy to meet up for a coffee or dial in for a free consultation. We always try to make the meeting useful and give as much advice as possible too!