Setting up makefile development environment for nrf51822 in Linux

I have recently set up the development environment for the nrf51822 SoC. I have a Development Kit (DK) of this IC, which for 99$ is quite a bang for the buck. A Development or Evaluation kit is necessary to access all the support documents, codes and binaries at Nordic Semiconductor’s page (or not, based on your web searching skills :P). The steps are based on the instructions provided here, so take a look at that helpful post too.

Step 1: For using the J-Link programmer/debugger, download the its software from here. You’ll need to have the serial number of the JLink unit to do this.  Download the 32 or 64 bit rpm or deb file based on the OS that you have. On 64 bit Ubuntu 13.10, the 4.80 deb file installs the software to /opt/SEGGER/JLink

Step 2: I prefer using the GNU-GCC toolchain to Sourcery Codebench.  Download the Linux pre-compiled tarball and extract to a convenient location.

Step 3: Register as a user in nordicsemi.com and enter the product key of your DK or EK to get access to the nrf51822 SDK. Download the nRF51-SDK-zip not the .msi installer. This SDK contains documentation and lots of example codes.  Extract the SDK to a convenient location.

Step 4: Download and extract this zip which is a compressed version of a demo project which lights up the green LED  and echos whatever is sent through the serial port. Many files  from the SDK that you get from step 3 are removed in this. This is because of the current license of the SDK which prevents us from sharing any of its files. Hopefully this will change soon if what is mentioned here is true.

Before deleting the SDK files, the file structure is as shown below. Copy the necessary files from the SDK as shown in the structure below.

|-- bin
|-- build
|-- include
| |-- board.h
| |-- gcc
| | |-- compiler_abstraction.h
| | |-- core_cm0.h
| | |-- core_cmFunc.h
| | `-- core_cmInstr.h
| |-- nrf
| | |-- common.h
| | |-- nordic_common.h
| | |-- nrf51_bitfields.h
| | |-- nrf51_deprecated.h
| | |-- nrf51.h
| | |-- nrf.h
| | `-- system_nrf51.h
| `-- peripherals
| |-- nrf_delay.h
| |-- nrf_gpio.h
| `-- simple_uart.h
|-- link
| |-- gcc_nrf51_blank_xxaa.ld
| |-- gcc_nrf51_common.ld
| `-- gcc_nrf51_s110_xxaa.ld
|-- Makefile
|-- obj
|-- src
| |-- gcc_startup_nrf51.s
| |-- main.c
| |-- nrf_delay.c
| |-- simple_uart.c
| `-- system_nrf51.c
`-- upload.sh

I have sourced this from this link. Thanks a lot. The makefile was wonderfully made. I have made it better in some aspects. The approach taken is that all the .c and .s (assembly) files must be in src folder. A ‘link’ folder is added to store the linker files. Few changes in the CFLAG has made this version compatible with GDB debugging in eclipse. Comment if you want some info about the makefile. More on setting up eclipse in the next post. The upload.sh file is made to be used by the ‘External Tools’ in eclipse.

Step 5:  Open the make file and edit the location of GNU-GCC tool-chain that you extracted in step 2. The GCC_INSTALL_ROOT and GCC_VERSION variables must be correct. Save it. Open Teminal (Ctrl + Alt + T) and navigate to where you have extracted the nrf51Demo project. Here are the make targets which I have used:

make all : Compiles the project
make clean : Cleans all object, output, map files etc.
make upload : Uploads to MCU the build/main.bin
make erase-all : Erases entire contents of memory

The next post in this series will be to setup eclipse to use this project with debugging. The zip file that is you’ve downloaded can be used to import an eclipse project if you want to get started already.

Introduction to PCA10000 and using JLink Software with it in Ubuntu

Recently I’ve started using the PCA10000 board, which is part of the nrf51822 Development Kit (DK). In this tiny amazing piece of hardware shown below on you can see the nrf51822 SoC. This IC is connected to a RGB led, a 16 MHz crystal, a 32.768  kHz crystal and a PCB antenna with its matching network. On the other side of the PCB is the SEGGER JLink Lite Cortex M unit. This can program and debug using the Serial Wire Debug (SWD) port of nrf51822. Another useful feature of this board is that the SEGGER JLink unit provides a serial port with hardware flow control (HWFC) to the computer that this dongle is connected to. This serial port is connected to the UART port of nrf51822. This UART port also has flow control pins i.e. RTS and CTS along with RX and TX pins. The user manual and this devzone forum answer by a Nordic Semiconductor employee say that HWFC must be used for the serial port to work, although I have got it to work without HWFC. (Update at the end)

PCA10000

Here are the steps to get the JLink software to work in a Linux distribution. I am using Ubuntu 13.10 now.

Installing JLink Software

Download the JLink software from this link. Since I have a 64-bit Ubuntu OS I have downloaded the 64-bit .deb file. You need to enter the serial number of the JLink unit that you have. This is usually found on a piece of paper stuck to it. It doesn’t matter if you enter the serial number either of the PCA10000 unit or of the stand alone JLink unit. Install this software by running the .deb or .rpm file.

Using JLinkExe

The JLink software is installed at /opt/SEGGER/JLink/ . The file that is used to access the nrf51822 is JLinkExe. It can be run with the command ./JLinkExe. Although it will complain that the unit is not connected, if it is not, it will still run. The question mark character ? is used to list all the available commands. Since I was did not find any website where this is listed, you can access the entire list of JLinkExe commands below.

prithvi@prithvi-ThinkPad-T420:~$ cd /opt/SEGGER/JLink/
prithvi@prithvi-ThinkPad-T420:/opt/SEGGER/JLink$ ./JLinkExe
SEGGER J-Link Commander V4.80 ('?' for help)
Compiled Dec 20 2013 19:40:54
Can not connect to J-Link via USB.
J-Link>?

Available commands are:
----------------------
f          Firmware info
h          halt
g          go
Sleep      Waits the given time (in milliseconds). Syntax: Sleep 
s          Single step the target chip
st         Show hardware status
hwinfo     Show hardware info
mem        Read memory. Syntax: mem  ,  (hex)
mem8       Read  8-bit items. Syntax: mem8  ,  (hex)
mem16      Read 16-bit items. Syntax: mem16 ,  (hex)
mem32      Read 32-bit items. Syntax: mem32 ,  (hex)
w1         Write  8-bit items. Syntax: w1 ,  (hex)
w2         Write 16-bit items. Syntax: w2 ,  (hex)
w4         Write 32-bit items. Syntax: w4 ,  (hex)
erase      Erase internal flash of selected device. Syntax: Erase
wm         Write test words. Syntax: wm 
is         Identify length of scan chain select register
ms         Measure length of scan chain. Syntax: ms 
mr         Measure RTCK react time. Syntax: mr
q          Quit
qc         Close JLink connection and quit
r          Reset target         (RESET)
rx         Reset target         (RESET). Syntax: rx 
RSetType   Set the current reset type. Syntax: RSetType 
Regs       Display contents of registers
wreg       Write register.   Syntax: wreg , 
moe        Shows mode-of-entry, meaning: Reason why CPU is halted
SetBP      Set breakpoint.   Syntax: SetBP  [A/T] [S/H]
SetWP      Set Watchpoint. Syntax:  [R/W] [ [] [A-Mask]]
ClrBP      Clear breakpoint. Syntax: ClrBP  <BP_Handle>
ClrWP      Clear watchpoint. Syntax: ClrWP  <WP_Handle>
VCatch     Write vector catch. Syntax: VCatch 
loadbin    Load binary file into target memory.
             Syntax: loadbin , 
savebin    Saves target memory into binary file.
             Syntax: savebin , , 
verifybin  Verfies if the specified binary is already in the target memory at the specified address.
             Syntax: verifybin , 
SetPC      Set the PC to specified value. Syntax: SetPC 
le         Change to little endian mode
be         Change to big endian mode
log        Enables log to file.  Syntax: log 
unlock     Unlocks a device. Syntax: unlock 
           Type unlock without  to get a list
           of supported device names.
           nRESET has to be connected
term       Test command to visualize printf output from the target device,
           using DCC (SEGGER DCC handler running on target)
ReadAP     Reads a CoreSight AP register.
           Note: First read returns the data of the previous read.
           An additional read of DP reg 3 is necessary to get the data.
ReadDP     Reads a CoreSight DP register.
           Note: For SWD data is returned immediately.
           For JTAG the data of the previous read is returned.
           An additional read of DP reg 3 is necessary to get the data.
WriteAP    Writes a CoreSight AP register.
WriteDP    Writes a CoreSight DP register.
SWDSelect  Selects SWD as interface and outputs
           the JTAG -> SWD swichting sequence.
SWDReadAP  Reads a CoreSight AP register via SWD.
           Note: First read returns the data of the previous read.
           An additional read of DP reg 3 is necessary to get the data.
SWDReadDP  Reads a CoreSight DP register via SWD.
           Note: Correct data is returned immediately.
SWDWriteAP Writes a CoreSight AP register via SWD.
SWDWriteDP Writes a CoreSight DP register via SWD.
Device     Selects a specific device J-Link shall connect to
           and performs a reconnect.
           In most cases explicit selection of the device is not necessary.
           Selecting a device enables the user to make use of the J-Link
           flash programming functionality as well as using unlimited
           breakpoints in flash memory.
           For some devices explicit device selection is mandatory in order
           to allow the DLL to perform special handling needed by the device.
ExpDevList Exports the device names from the DLL internal
           device list to a text file
             Syntax: ExpDevList 
PowerTrace Perform power trace (not supported by all models)
Syntax: PowerTrace  [ ]
: File to store power trace data to
: 32-bit mask to specify what channels shall be enabled
: Sampling frequency in Hz (0 == max)
:       0: No reference count
                     1: Number of bytes transmitted on SWO
---- CP15 ------------
rce        Read CP15.  Syntax: rce , , , 
wce        Write CP15. Syntax: wce , , , , 
---- ICE -------------
Ice        Show state of the embedded ice macrocell (ICE breaker)
ri         Read Ice reg.  Syntax: ri (hex)
wi         Write Ice reg. Syntax: wi , (hex)
---- TRACE -----------
TAddBranch TRACE - Add branch instruction to trace buffer. Paras:,
TAddInst   TRACE - Add (non-branch) instruction to trace buffer. Syntax: 
TClear     TRACE - Clear buffer
TSetSize   TRACE - Set Size of trace buffer
TSetFormat TRACE - SetFormat
TSR        TRACE - Show Regions (and analyze trace buffer)
TStart     TRACE - Start
TStop      TRACE - Stop
---- SWO -------------
SWOSpeed   SWO - Show supported speeds
SWOStart   SWO - Start
SWOStop    SWO - Stop
SWOStat    SWO - Display SWO status
SWORead    SWO - Read and display SWO data
SWOShow    SWO - Read and analyze SWO data
SWOFlush   SWO - Flush data
SWOView    SWO - View terminal data
---- PERIODIC --------
PERConf    PERIODIC - Configure
PERStart   PERIODIC - Start
PERStop    PERIODIC - Stop
PERStat    PERIODIC - Display status
PERRead    PERIODIC - Read and display data
PERShow    PERIODIC - Read and analyze data
---- File I/O --------
fwrite     Write file to emulator
fread      Read file from emulator
fshow      Read and display file from emulator
fdelete    Delete file on emulator
fsize      Display size of file on emulator
---- Test ------------
TestHaltGo   Run go/halt 1000 times
TestStep     Run step 1000 times
TestCSpeed   Measure CPU speed.
             Parameters: []
TestWSpeed   Measure download speed into target memory.
             Parameters:  [ []]
TestRSpeed   Measure upload speed from target memory.
             Parameters: [ [] []]
TestNWSpeed  Measure network download speed.
             Parameters: [ []]
TestNRSpeed  Measure network upload speed.
             Parameters: [ []]
---- JTAG ------------
Config     Set number of IR/DR bits before ARM device.
             Syntax: Config , 
speed      Set target interface speed. Syntax: speed |auto|adaptive, e.g. speed 2000, speed a
i          Read JTAG Id (Host CPU)
wjc        Write JTAG command (IR). Syntax: wjc (hex)
wjd        Write JTAG data (DR). Syntax: wjd (hex), (dec)
RTAP       Reset TAP Controller using state machine (111110)
wjraw      Write Raw JTAG data. Syntax: wjraw <NumBits(dec)>, , 
rt         Reset TAP Controller (nTRST)
---- JTAG-Hardware ---
c00        Create clock with TDI = TMS = 0
c          Clock
tck0       Clear TCK
tck1       Set   TCK
0          Clear TDI
1          Set   TDI
t0         Clear TMS
t1         Set   TMS
trst0      Clear TRST
trst1      Set   TRST
r0         Clear RESET
r1         Set   RESET
---- Connection ------
usb        Connect to J-Link via USB.  Syntax: usb , where port is 0..3
ip         Connect to J-Link ARM Pro or J-Link TCP/IP Server via TCP/IP.
           Syntax: ip <ip_addr>
---- Configuration ---
si         Select target interface. Syntax: si ,
           where 0=JTAG and 1=SWD.
power      Switch power supply for target. Syntax: power  [perm],
           where State is either On or Off. Example: power on perm
wconf      Write configuration byte. Syntax: wconf , 
rconf      Read configuration bytes. Syntax: rconf
ipaddr     Show/Assign IP address and subnetmask of/to the connected J-Link.
gwaddr     Show/Assign network gateway address of/to the connected J-Link.
dnsaddr    Show/Assign network DNS server address of/to the connected J-Link.
conf       Show configuration of the connected J-Link.
ecp        Enable the  J-Link control panel.
calibrate  Calibrate the target current measurement.
selemu     Select a emulator to communicate with,
           from a list of all emulators which are connected to the host
           The interfaces to search on, can be specified
             Syntax: selemu [  ...]
ShowEmuList Shows a list of all emulators which are connected to the host.
            The interfaces to search on, can be specified.
             Syntax: ShowEmuList [  ...]
----------------------
NOTE: Specifying a filename in command line
will start J-Link Commander in script mode.
JLinkExe>

As mentioned in the last line of the help text, a script file can be used to do many tasks together. This is used for doing things such as programming a binary output file or wiping the flash memory. Setting up the development environment and using these scripts will be addressed in the next post.

Using the serial port in PCA10000

Plugging in the PCA10000 in a USB port after installing the JLink software should give the following output in dmesg in terminal. Update: As Jeshwanth pointed out, JLink software is not required for the ACM serial port to work. My mistake.

[ 3420.454164] usb 2-1.2: new high-speed USB device number 4 using ehci-pci
[ 3420.547137] usb 2-1.2: New USB device found, idVendor=1366, idProduct=0105
[ 3420.547148] usb 2-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 3420.547154] usb 2-1.2: Product: J-Link
[ 3420.547159] usb 2-1.2: Manufacturer: SEGGER
[ 3420.547163] usb 2-1.2: SerialNumber: 000480106358
[ 3420.547705] cdc_acm 2-1.2:1.0: This device cannot do calls on its own. It is not a modem.
[ 3420.547901] cdc_acm 2-1.2:1.0: ttyACM3: USB ACM device

Here you can see that ttyACM3 device has been added. You have to see this device listed when you see the contents of /dev with the command ls /dev. Usually ttyUSBx devices are added in a USB to serial converter and this is the first time that I am using a ttyACMx device. It required a bit of time poking around to realize that the way they work is the same.
A good application to use the serial port is cutecom (if you don’t like minicom’s user interface). Install it with sudo apt-get install cutecom and open it with sudo cutecom. Don’t forget sudo. Below is a screenshot of CuteCom working with PCA10000 running a basic serial echo (re-transmitting what is sent) code. Notice that the device is /dev/ttyACM3 and the hardware flow control is turned off. Update: Although, the Handshake field in Cutecom is turned off, the program compiled for nrf51822 must have HWFC set as true for it to work. It seems that any changes to any .h file will not make the GCC compiler to compile again as it things nothing has changes. A clean and compiling again will reflect the changes made in .h file. So, after cleaning and recompiling after setting the HWFC to false the serial echo did not work.

CuteCom

PS. Sorry for the horribly small column width. Will fix it soon.