jenswilly.dk


LPC11U24/LPC1347 JTAG/SWD debugging with LPC-Link

23. September 2013 21:41 by Jens Willy Johannsen
Categories: ARM

I had some problems getting my ROV on-board controller (which uses a LPC1347) programmed from LPCXpresso.

After doing the research I should have done before I had the PCBs made (doh), I found out I had messed up the SWD programming/debugging connections.

And so, in order to spare anyone else the same trouble, here is a small recap of which wires to connect to what.

Connections from LPC11U24/LPC1347

These are the minimal connections from the MCU to the LPC-Link:

Pin name LQFP48 pin no. Connect to
#RESET/PIO0_0 3 SWD pin 10 (#RST)
SWDIO/PIO0_15/AD4/ 25 CT32B1_MAT2 39 SWD pin 2
SWCLK/PIO0_10/SCK0/CT16B0_MAT2 29 SWD pin 4

Note: It is not necessary to have pull-up resistor on #RESET (or any other pin) unless other parts of the circuit might affect the levels since it is internally pulled up to VDD.

Connections from JTAG/SWD

These are the minimal connections from the LPC-Link to the MCU board.

Pin number Connect to LQFP48 pin no. Comment
1 3.3V on MCU 8, 44
2 SWDIO 39
3 n/c Optional GND (see note 1)
4 SWCLK 29
5 n/c Optional GND (see note 1)
6 n/c Optional SWO (see note 2)
7 n/c
8 n/c
9 GND 5, 41
10 #RESET 3

Note 1: It is sufficient to connect one of the GND pins (e.g. SWD pin 9) as pins 3, 5 and 9 are all connected on the LPC-Link.

Note 2: SWD pin 6 can be connected to PIO0_9/MOSI0/CT16B0_MAT1/SWO (LQFP pin 28) but this is not required.

Pin numbering

This image shows the pin numbering on the LPC-Link. Pin 1 has been marked in red.

Do yourself a favor and perform a continuity check from the LPC-Link side to your MCU board to make sure which pins go where.

LPC-Link pinout

LPC-Link pinout

(Image composited from images from http://www.keil.com and http://www.embeddedartists.com.)

Be aware that the 0.1" pins on the right edge of the board do not follow the JTAG pin numbering but have these connections:

  1. VCC
  2. SWDIO
  3. SWCLK
  4. SWO
  5. TDI
  6. #RESET
  7. EXT. PWR
  8. GND

The required pins are 1, 2, 3, 6 and 8.

Connection procedure

Sometimes LPCXpresso can't initialize the LPC-Link even though it is connected. I have found that following the following procedure works every time:

  1. Launch LPCXpresso IDE
  2. Power up device
  3. Attach to LPC-Link
  4. Connect LPC-Link to computer by USB
  5. Debug firmware from LPCXpresso
No comments No comments »

Repetitive Interrupt Timer on LPC1347

9. March 2013 19:30 by Jens Willy Johannsen
Categories: ARM

For my ROV project I need to control an RC servo to tilt the camera up and down. I've gotten that working nicely using a 16-bit timer to generate an appropriate PWM waveform.

But when I change the the position by a lot – for example, going from one endpoint to the middle position – the servo moves too fast. (Which, incidentally, draws a huge current which makes my 5 V rail drop enough to reset the MAX7456 – but that is fixable.) So I need to slow the movement down by gradually changing the position instead of jumping straight from one position to another.

The full servo movement corresponds to a change in timer match value by 1000 (the PWM timer is set up so the match values correspond to PWM pulse on-time in microseconds so minimum is 1000 and maximum is 2000). I would like the full range of movement to take one second so I thought that changing the position in increments of 10 at a frequency of 100 sounds about right.

Unfortunately, I'm fresh out of timers: CT32B0 and -1 are used for motor control PWM, CT16B0 is used for periodic analog-to-digital conversions (for the pressure sensor used as depth gauge) and CT16B1 is used for servo PWM. Yeah, sure, I guess I could use a timer for more than one purpose but since the LPC1347 actually has one more timer, I might as well use that: the Repetitive Interrupt Timer.

The Repetitive Interrupt Timer (RIT for short) generates interrupts every X clock cycles and if I configure the timer to fire an interrupt every 720,000 clock cycles I get a 100 Hz interrupt (on a 72 HMz PCLK) in which I can move the servo if necessary. Nice.

This is the code I came up with:

Repetitive Interrupt Timer on LPC1347

// MIN and MAX macros
#ifndef MIN
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif

// Servo position variables
volatile uint16_t servo_position;
volatile uint16_t servo_target;

// Stop RI timer – otherwise we can't reset the counter
LPC_RITIMER->CTRL = 0;

// Init RI timer (we don't need to enable timer – it is always running as per the updated User Manual UM10524)
LPC_RITIMER->COMPVAL = 720000;
LPC_RITIMER->COMPVAL_H = 0;

// Reset counter (otherwise it might already be above the compare value and then it would take a loong time to overflow to zero)
LPC_RITIMER->COUNTER = 0;
LPC_RITIMER->COUNTER_H = 0;

// Set RITENCLR (clear on match), RITENBR (halt timer on debug) and RITEN (start timer)
LPC_RITIMER->CTRL = (1<< 1) | (1<< 2) | (1<< 3);

// Enable RIT interrupt
NVIC_EnableIRQ( RIT_IRQn ); 

// Interrupt routine 
// (Yes, it's a little weird that the interrupt routine is called OSTIMER but the NVIC interrupt is called RIT_IRQn)
void OSTIMER_IRQHandler()
{
    // Clear interrupt
    LPC_RITIMER->CTRL |= (1<< 0);   // Write RITINT to clear

    // If we're at target, do nothing
    if( servo_position == servo_target )
        return;

    if( servo_target > servo_position )
        servo_position += MIN( servo_target - servo_position, 10 );
    else // Not equal and not greater than, so it's less than – we don't need to check
        servo_position -= MIN( servo_position - servo_target, 10 );
}
Comments 4 comments »

SPI on LPC1347 vs capacitance

5. February 2013 22:07 by Jens Willy Johannsen
Categories: ARM

Or "Capacitance matters – who'd've thunk it"

I am using SPI to talk to a MAX7456 video overlay IC from an LPC1347 MCU in my ROV project.

That should be easy enough since the LPC1347 contains twp SPI compatible synchronous serial ports ("SSP" for short). Perusing the manual and some code examples I came up with code to initialize the SSP for SPI comms and to send SPI data.

But, alas, it didn't work :(

Connecting my trusty Saleae Logic analyzer I saw that the CS line was toggled low and then high again for every byte. Which the MAX7456 apparently doesn't like – it wants the CS line to be low for the entire command (which consists of several bytes) – just as described in the datasheet.

So I switched to manually toggling a GPIO line low before transmitting SPI data and then high again when transmission is done. Like this:

#define MAX7456_CS_ON LPC_GPIO->CLR[ 1 ] = (1<< 13)
#define MAX7456_CS_OFF LPC_GPIO->SET[ 1 ] = (1<< 13)

MAX7456_CS_ON;

spi_transfer(VM0_reg);
spi_transfer(MAX7456_reset);

MAX7456_CS_OFF;

And, for reference, the spi_transfer() function looks like this:

void spi_transfer( uint8_t data )
{
    // Wait until SSP is not busy and TX FIFO is not full
    while ( (LPC_SSP0->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF )
        ;

    // Send data
    LPC_SSP0->DR = data;
}

But that didn't work either. Looking at the logic analyzer it turned out that CS came low several microseconds after the SPI transmission started. Weird, since the the GPIO pin is set low before I start the SPI. I also tried using the byte pin and word pin registers but the result was the same.

So it just looks like the GPIO is just really, really slow. What I finally came up with that works was this:

#define MAX7456_CS_ON { uint8_t i; LPC_GPIO->CLR[ 1 ] = (1<< 13); for( i=0; i<48; i++ ) __NOP(); }
#define MAX7456_CS_OFF LPC_GPIO->SET[ 1 ] = (1<< 13)

In other words: let the CPU wait for 48 clock cycles after setting the pin low before trying to do something else.

On the logic analyzer, it looks like this:

Logic analyzer capture. With delay.

Logic analyzer capture. With delay.

Still weird though. Until I connected a scope instead of a logic analyzer. Then it looked like this without the delay:

Scope capture. Without delay.

Scope capture. Without delay.

And this with the delay:

Scope capture. With delay.

Scope capture. With delay.

So it looks like the delay is, in fact, not the MCU's GPIO that is slow but rather capacitance. So even though the pin was toggled low the capacitance caused the voltage to decay slowly (relatively speaking) instead of instantly. So without the delay, the voltage never dropped low enough for the MAX7456 to consider the CS low. Now bear in mind that the pin is connected to the MAX7456 though the LPCXpresso board, the LPCXpresso Base Board, a jumper wire and then the MAX7456 breakout board. All of which have non-zero capacitance.

In other words: when working with high-speed (in this case 4 MHz) signals, make sure you design the board with that in mind and minimize capacitance (and inductance).

Unfortunately, I have no experience with that kind of semi-advanced PCB layout. Fortunately I can fix it in software and the delay I introduce will not pose a problem in this case.

Comments 2 comments »

Soft UART on LPC13xx

23. January 2013 11:32 by Jens Willy Johannsen
Categories: ARM | Projects

For the ROV project I need two UART connections (one for RS485 to the onboard controller and one for receiving input from the VNC2 USB host controller).

And since the LPC1347 only has one UART I needed a soft UART for one of the connections. Fortunately for me, NXP provides an implementation in AN10955. There was only one problem with it: it doesn't work. Or rather, it works for a while and then stops receiving anything (scoping the UART line confirmed that the VNC2 chip continued to send data so the problem had to be in the soft UART code).

Yea, intermittent errors – what's not to like… (Read on for the problem and the solution.)

Read the entire post »

Comments 2 comments »

USB joystick as input to MCU

25. October 2012 14:03 by Jens Willy Johannsen
Categories: Projects

As kind of a bigger, more long-term project I've been thinking about building a small ROV. This is in no way a novel idea – there are lots and lots og DIY ROV projects out there (Google: build your own ROV). I live by a canal in Copenhagen habour so it would be fun to have a small underwater robot to play with.

There is a lot of hardware going into a ROV project so there's lots of potential for learning new technologies. One of the components is, of course, the control input device. I figured I would forego the usual clunky four-way tact switches and use a decent USB joystick instead – a Saitek Cyborg EVO to be specific. It has pitch, roll, yaw and throttle axes as well as a thumb hat switch and about a million push buttons.

This is a USB joystick and it uses the USB HID protocol. So I need the MCU to work as a USB host. This either involves a big nasty pile of firmware code or a MCU with ROM-based USB host drivers.
My current MCU of choice, the LPC1347, does not have USB host capabilities, but its bigger (but older) brother, the LPC1768 (and other in the LPC17xx series) does have USB host drivers.

However, instead of switching to another MCU I've decided use a dedicated USB host IC. That being the FTDI Vinculum-II. This chip will handle all the USB stuff: enumerating, connecting and so on. And it will be programmed with firmware that simply echoes HID data from the joystick to the MCU using either UART or SPI.

So – off to the store to get myself a development board version of the VNC2 (this one) and we'll see if I can get it working with the joystick…

No comments No comments »

nxpUSBlib on LPC1347

5. October 2012 14:01 by Jens Willy Johannsen
Categories: ARM

Since I had some problems gettings USB CDC working I decided to try using NXP's nxpUSBlib instead of the more simple examples that I only got almost working. But I ran into a couple of problems...

LPC1347 support

The first problem was getting the thing compiling for the LPC1347. The most recent version (0.97) does support the LPC1347 but not quite.

Having downloaded the archive and imported everything into Code Red LPCXpresso IDE as per the readme, I tried to configure the BSP (development board), CDL (CMSIS and device) and nxpUSBlib projects for the LPC1347 MCU. No problems.
But when I tried to select the LPC1347 for the Example_VirtualSerialDevice project it turned out that there was no such build configuration. There is a LPC13Uxx configuration for the Example_MassStorageDevice, however.

Read the entire post »

Comments 1 comment »

Moving to LPCXpresso

23. September 2012 13:47 by Jens Willy Johannsen
Categories: ARM | Projects

I’ve made quite a bit of headway with the firmware for the GPS Tracker project but there are still some problems – mainly with the command parser and the USB CDC interface.

So I decided I needed some way of debugging the firmware. After looking at several options (they have to run on Mac OS X), I decided to get a LPC1347-based LPCXpresso.

The LPCXpresso consists of two parts:

  1. An LPC MCU with a minimal amount of support components: crystal, capacitors, an LED and a mini-USB socket with the required resistors and PNP transistor.
  2. The “LPC-Link” which is a programmer and JTAG debugger which connects to the computer by USB. The LPC Link can actually be severed from the MCU part of the board and will then work as a normal JTAG debugger which can be connected to MCUs (LPCXpresso or otherwise) using a 10-pin connector.

The LPCXpresso also comes with a free version of Code Red’s Eclipse-based IDE with built-in/preconfigured support for the GNU tool chain and standard C libraries and debugging views for inspecting memory and peripherals and whatnot.

Read more about the LPCXpresso here: http://ics.nxp.com/lpcxpresso and about the IDE here: http://www.code-red-tech.com/lpcxpresso.php.

I prefer the LPCXpresso to the mbed because the MCU board contains no extra components (compared to what I will use on my own boards) and all code is standard C and CMSIS libraries (so no proprietary firmware environment and libraries) – and still I have the ability to debug code and inspect memory at will.

LPC11U24 + LPC1343 –> LPC1347

The LPCXpresso is available with a number of different LPC MCUs. I chose the LPC1347-based one.

Basically, the LPC1347 is a newer version of the LPC1343 and it has the same GPIO structure as the LPC11Uxx devices and the same USB ROM drivers and it now has EEPROM as well. Read this blog entry on microBuilder.eu for a comparison between the LPC1343 and the LPC1347.

I have decided to focus on only one ARM MCU instead of both the LPC11U24 and the LPC1343 – and that will be the LPC1347 (for now at least). Yes, it has a slightly higher power consumption than the LPC11Uxx but on the other hand it is faster and has a Cortex M3 core instead of a Cortex M0 core.

So the plan is:

  1. Make the necessary changes to compile the current firmware code for an LPC1347 (which shouldn’t be too much of a hassle since peripherals for the LPC11U24 and the LPC1347 are pretty much the same) in the LPCXpresso IDE (removing the current linker script and CMSIS files).
  2. Rebuild the breadboard prototype using the LPCXpresso.
  3. Debug, find the problems and fix them…
Comments 2 comments »