Sunday, February 10, 2013

Free Cortex debugger

Emulator company iSystem offers free Cortex debugger. There are couple of options on how to get it. Most intriguing is the DIY option. The design is similar to STM32F4-Discovery board. I successfully managed to make it with the actual Discovery board. Following is how.

To supply the board from device USB port the connection from PA9 to 5V is needed (red wire). Further the BOOT0 needs to be connected to 3V (brown wire) to boot the device in DFU mode after power on. Also, I had onboard debugger disabled.

Needed connections


With these connections I followed the official guide on how to program the initial firmware (with iTAG_Public.exe) to STM simulating J2 (see documentation) with brown wire. There were some problems programming it from 32bit virtual machine. It worked on my 64bit W7 machine. Debugging was later possible in virtual machine.

Debugger works with free iTAG winIDEA IDE. Updating the firmware with winIDEA worked as described.

Output debug signals can be found in iTAG schematics (also available). I connected them to other STM32F4-Discovery board and downloaded the RTOS winIDEA sample to target on the other board for test. Supply for target was taken from debugger board.

Debugger - target connection (BOOT wire removed)


Target details

Debugger details

Debugging in winIDEA
Links:
Some points:
  • Schematics, utility, gerber files, iTAG winIDEA IDE available for free online
  • No registration required
  • No download size limit
  • GCC 4.7.0 compiler build for ARM/Cortex projects included with winIDEA
  • No trace functionality
There are two optional connectors on the official iTAG board. They seem like analog and digital extension ports like on some professional tools the company offers. However there are no options to configure them. Also, the SWO signal is connected to UART Rx pin on the debugger. This could mean that SWO trace option was planed. Hopefully the functionality will come with updates.

Tuesday, February 5, 2013

Cortex debug condition assertion

Used to popular ASSERT(condition) macro? Code below stops on faulty condition when debugging Cortex CPU. BE CAREFUL: use code build with _DEBUG or DEBUG define when debugging  BUT DON'T use same code without debugger.

#if defined ( _DEBUG ) || defined ( DEBUG )
  #define ASSERT(expr) { if ( !(expr) ) { __ASM__(" bkpt #0"); } }
#else
  #define ASSERT(...) { }
#endif

Usage:
void someFunc(int inputParam)
{
  ASSERT( inputParam < 5 );  ///< execution will stop here if inputParam >= 5
  ...
}

Friday, February 1, 2013

Stellaris LaunchPad with external debugger

Finally a board with integrated debugger and an official option for external debugger. I'm talking about EK-LM4F120XL. To disable integrated debugger the EXT_DBG signal must be tied low. I'm doing extended debug connectivity options demonstrations. Find below photos for both standard JTAG and Cortex connectors in combination with JTAG and SWD debug protocol with parallel or serial trace and without it.

Cortex debug connector

JTAG debug protocol + parallel trace


JTAG debug protocol


SWD debug protocol + parallel trace


SWD debug protocol + serial trace


SWD debug protocol


Jtag debug connector

JTAG debug protocol


SWD debug protocol + serial trace


SWD debug protocol


Friday, January 25, 2013

Kinetis FRDM-KL25Z with external debugger

Here is how to attach external debugger to Kinetis CPU on FRDM-KL25Z board. Like we are used to by now the debug connector on the boards with an on-board debugger is used to connect the on-board debugger to board without it. Anyway the debug connector can be used as input when on-board debugger is put in reset. This is done with jumper on the other debug connector. I.e. on the debug connector for the on-board debugger (debugging a debugger - there's a thought for you :) ).



You might need to chip away a bit of debug connector housing due to C7.
Probably not if you are just using pinheader.

Monday, December 17, 2012

CortexM exception context

You can get exception context inside exception handler from memory. On Cortex M cores the context is pushed on stack. I have prepared the struct type with layout equal to the exception context. The context is available by assigning the address of context in memory to local pointer to variable of prepared struct type.

The example bellow was made for GCC compiler where you can easily specify local variable as register. This is unnecessary for local pointer variable but must be done for LR which holds information about exception context. Notice the naked attribute to handler function. It is needed so that the handler has no function prologue which could change SP. SP (main or process) actually holds the address of the exception context.

For easier debugging the software breakpoint is added at the end of handler and automatic handler catch functionality can be disabled so that CPU stops at breakpoint (not on handler entry).




typedef struct
{
  unsigned long m_dwExR0;
  unsigned long m_dwExR1;
  unsigned long m_dwExR2;
  unsigned long m_dwExR3;
  unsigned long m_dwExR12;
  unsigned long m_dwExLR;
  unsigned long m_dwExPC;
  unsigned long m_dwExPSR;
}SCortexM3ExContext;

__attribute__( ( naked ) )
void HardFaultHandler()
{
  register SCortexM3ExContext * psCortexM3ExContext __asm("r0");
  register unsigned long dwLR __asm("lr");

  if ( dwLR & 4 )
    asm(" mrs r0, psp");
  else
    asm(" mrs r0, msp");

  asm(" BKPT");
  while ( 1 );
}

Wednesday, December 12, 2012

Cortex exceptions entry and return

There is a difference in exception handling on CortexM and CortexR/A cores. You can find details in ARM Architecture Reference Manuals (2 documents - separate for M and R/A).

Exception entry

Cortex M

The addresses of exception (interrupt) handlers must be listed in vector table at address specified in VTOR register. Each exception (interrupt) has predefined offset location in vector table. Be sure to have LSB set in vector table entry values (denoting THUMB destination).

Cortex R and A

32 bit jump instructions with destination address of corresponding handler functions must be listed from address 0x00000000 or 0xFFFF0000 or VBAR or HVBAR  based on SCTLR.V bit, Security Extensions and Virtualization Extensions implementation and settings. Be sure to use correct branch instruction based on destination handler THUMB or ARM state.


Exception return

Cortex M

Exception  return is detected by writing a value with bits 31 .. 28 set (0xFxxxxxxx) to PC (R15). Conveniently the appropriate value is written to LR (R14) when the exception is taken. So basically no extra care is needed when returning from handler. Jump to LR as for return from subroutine is enough.

Cortex R and A

Exception return is done with special instruction based on architectue version and privilege level. Possible instructions are SUBS, MOVS, RFE, LDM and ERET.
With GCC the handler functions can be decorated with attribute denoting that it is an exception handler. GCC will then generate proper return instructions in function epilogue. Possible entries for GCC interrupt attribute are: IRQ, FIQ, SWI, ABORT and UNDEF.

Thursday, September 27, 2012

Create new folder - first couple of moments of program flow on STM32

I'm working on a new project with STM32F4. I got stuck on USB communication and wanted to compare my project to the mass storage sample that comes with the library from ST. I recorded the first couple of seconds of the program flow on the STM32 after clicking the "Create new folder" in Windows explorer. Below are the screen shoots of the recorded flow on the STM32 with the couple of zoomed in regions. At the end there are also statistics.

Some notes:
  • I set the trigger to SCSI write function and recording started when I clicked the new folder button.
  • Not all function are shown. I have set the filter to only show the USB related ones.
  • Full speed USB was configured in project.

First, the complete 7sec recording. Interesting stuff is going on in the first half of second. Next images show that area zoomed in. (Click images to see them larger.)

First half of second. Most functions are still marked purple and seem to be running in parallel. This is because in time covered by one pixel width the function was called and also returned.


30ms span. There are still some functions that are called too many times to show at this zoom level.

2ms span. Most functions are marked red. The pale red in function flow shows when the execution was outside the function body due to subroutine call.

Finally 5us span where also the calls to the shortest functions are clearly seen.


 This is the statistics view of the same recording. Note the overall time spent in each function and the function call count.

Recordings were made with winIDEA IDE and IC5000 emulator from iSYSTEM.

Thursday, August 9, 2012

Kinetis TWR-K70 main board mod for external debugger with trace

When plugging TWR main board to USB the integrated debugger enumerates and wants to install drivers. This can be annoying when you use external debugger and don't have drivers for on-board debugger installed at all. This debugger can be disabled with jumper connecting pins 2 and 4 on BDM connector J14. But with this change only the power switch for the rest of the board is permanently switched off. It can be forced to on state with applying high level on pin 4 of U2. Supply voltage is available on BDM connector.



Trace clock signal for parallel trace needs to be connected to external debug connector via R137 which is not populated by default.


Tuesday, May 1, 2012

WinUSB communication with STM32 (Part 4: Software)


Time for some bulk communication. VS project that I added to sources shows steps which are needed for communication. Project uses the Setupapi for device enumeration and obtaining the handle to device. It further uses the winusb to communicate with device.

After obtaining the handle to device and initializing it there can be multiple communication cycles. The communication cycle has the following steps:

  1. reset the communication channel (control EP)
  2. send data (bulk EP)
  3. send end of data message (control EP)
  4. poll status until "READY" or "ERROR" (control EP)
  5. read data size of response (control EP)
  6. read response data (bulk EP).
The source is mostly copied from MSDN with some changes and additions. An improvement to the library would be an object type which would encapsulate all this functionality and expose nice interface to communicate with device. An alternative could be  libusb-win32 or libusbK or other USB libraries. I haven't checked these in detail. If interested check libwdi. There is some information on Windows 8 integrated support for devices like this (no driver needed for WCID devices!).

[Update - WinXP (SP2) and W7 support driver information descriptors; See my next project]

Test application output.

Check project wiki to get build instructions.

This is the forth post in this series (of total 4 posts). See 12, 3.

[Update - I have a new WinUSB device project with STM32F407 without the need for Windows side driver info (.inf and .cat files) ]

Sunday, April 29, 2012

WinUSB communication with STM32 (Part 3: Driver)

WinUSB driver must be linked to device. This means creating a driver INF file specifying WinUSB as driver for device with specific USB VID and PID. To complicate a bit further this information needs to be signed. That is done by signing a catalog file (CAT) created from INF file. Windows Driver Kit (WDK) includes all the tools to do it.
Driver (code) signing was introduced to help prevent the installation of software that is not trusted. From what I understand about driver signing is that Windows trust some global certificate authorities (CA). They then issue a code signing certificates containing the publishers' information to software publishers. By this they are saying that the publisher was verified by them. They do it manually like call the person/company which issued a request for certificate and verify their information. For this they charge a yearly fee. The result is a class 3 certificate which publisher uses to sign his software. On installation/execution Windows pop up a dialog asking if you trust the publisher named as specified in signature of the executable which you wish to install/run. Publisher can also send his driver directly to Microsoft for testing and signing. It is called WHQL Testing. I'm not sure but I think that drivers tested and signed by MS are installed without any warnings. Read more about it on wiki. And I believe this isn't free either.
Free of charge alternative is an open source code signing certificate issued by same trusted CA (e.g. http://www.certum.eu). The requirement is that "Open source" keywords are stated in certificate information (e.g. the Name field of certificate is "<publisher name>. Open Source Developer")
Another free of charge alternative for debugging is so called self-signed certificate. This is a certificate created by developer. I created a script that:
  1. creates the certificates,
  2. copies the redistributables from WDK,
  3. creates usbID.h file containing the IDs for USB descriptor which must match the INF file,  
  4. creates the INF file,
  5. checks the INF file,
  6. creates the CAT file from INF file and
  7. signs the CAT file with created certificate
I did this rather than publish a driver ready to install because it depends on personal information. Well I could distribute my self-signed certificate but I don't own a USB vendor ID. And since you have to have your own in the INF file the signed driver is no use to you because you must change it.

USB Vendor ID is another story to this. If you are serious and plan to sell USB devices you should apply for USB VID. It will be assigned to you after one time purchase. To additionally use the USB logo on the device you must pay a yearly fee... I think.

The script actually creates two certificates. First is your CA certificate. Second is code signing certificate issued by your CA. I omitted the installation of created CA certificate to "Root trusted certificates" because it seems to make no difference. First I thought that there will be no warnings if I put the created CA certificate next to other trusted CAs. But the Windows still pop up even more annoying warning saying that publisher can not be verified. I also tried generating the certificates with OpenSSL with no success.


Anyway, driver installation completes successfully if you choose to install anyway. The device is then displayed in the Device Manager as shown below.


Automatic installation can be done with dpinst.exe toll (part of WDK redistributables). But I didn't deal with why dpinst warning pops up saying that the publisher of dpinst is unknown. Maybe because it was ran from script?


To see details of all operations see the script.

This is the third post in this series (of total 4 posts). See 124.

[Update - I have a new WinUSB device project with STM32F407 without the need for Windows side driver info (.inf and .cat files) ]

Tuesday, April 24, 2012

WinUSB communication with STM32 (Part 2: Firmware)

The sources are available at Google code project.

I decided to make a communication pipes implementation as library so that it can be used with other USB hardware. The library uses two bulk endpoints and control endpoint. One bulk endpoint is for receiving the data and the other for sending the data. The default control endpoint (EP0) is used for communication control.
User's code should repeatedly call single function in library which does nothing while no data is received and calls user's function when new packet arrives.

Larger communication buffers are better for faster communication. To improve it even more the USB implementation should use double buffered endpoints - not the case at the moment.

This is the second post in this series (of total 4 posts). See 134

[Update - I have a new WinUSB device project with STM32F407 without the need for Windows side driver info (.inf and .cat files) ]

Wednesday, April 18, 2012

LPCXpresso upgrade for external debugger

I found long lost LPCXpresso under pile of paper when tidying the desk - you just have to do it every now and then :). Below are the images of modification for the board to work with external debugger. When added jumper is closed you can use external debugger with standard 10pin Cortex connector. If your debugger uses VCC pin (1) for target supply detection you should shorten the R29. My board came without R29 placed.

Added jumper holds integrated debugger in reset.

I soldered the pinhead on both sides for robustness.

Tuesday, April 17, 2012

WinUSB communication with STM32 (Part 1: Intro)

Aren't you fed up with putting a USB to serial converter in your embedded design while you have a USB capable device already in the design? Any other approach opens a can of worms though. Custom driver, certificate to sign it, USB vendor ID (2000$ at the moment), how to communicate with device on a layer above USB? But it is nice when OS pops up your name when your device is plugged in USB port. WinUSB is middle ground with tradeoffs one might consider.

I wanted to test the use of WinUSB with STM32F103 for some time now. When I finally got time I created a demo project. It shows basic request - response communication.
WinUSB kernel mode driver enables raw communication through USB pipes. In other words you can communicate with your USB device directly from application on the PC. So there is only code for application and code for firmware. Presuming you are not making standard USB class device like Mass Storage or HID. You might not even need custom PC side software in this case.
Furthermore the libraries to communicate are written for both ends to some extent. There SetupAPI and WinUSB on Windows side while ST has libraries for everything.
To get a taste check images below. I will post more about it in the future and probably publish the sources after I clean and organize them.

VS showing sent data.

winIDEA showing same received data on STM32.

This is the first post in this series (of total 4 posts). See  234.

[Update - I have a new WinUSB device project with STM32F407 without the need for Windows side driver info (.inf and .cat files) ]


Sunday, April 8, 2012

LCD Type On Cheap STM32 Camera Board From eBay

I bought a camera board with 2.8 inch TFT LCD and STM32 on eBay for 50 bucks some time ago. The primary project was put aside after I lost my initial excitement and motivation. After almost a year I was organizing libraries from ST for STM32 for some other purposes. I came across GUI library and remembered that I have the board laying around and decided to test the GUI library.


STM32 camera board (SWD debugging; I rewired the uSD  soon after I bought it)
Circle on functional LCD at the end (original FW displayed the picture from camera)
LCD connection - it is a 37pin connector

Soon I discovered that there are no usable markings for the LCD. I got the schematic from the seller and the demo project sources which were zipped in password protected archive. Nothing found with Google had any LCD type information. I had no way to determine how to set up the communication with the LCD. I didn't decide to query the seller for the password due to his lag in replying - I waited a week to get the mentioned files when I bought the board.
I assumed that the design is based on a evaluation board from ST. There are drives in ST libraries for the LCDs that ST uses on their boards.
Luckily I still have the original firmware (binary file only) to see how the LCD is used. I have programmed it and set up my debugger (winIDEA - I use iSystem emulator) to break on access to registers for the port to which LCD was connected. Fortunately only one port is used for LCD (PORTB). After each RUN the application stopped on each IO port signal change and I could read the signals values.

Watchpoint breakpoints setup in winIDEA
Port registers display in winIDEA

To automate the process of running, waiting to stop and reading the value I wrote a Python script. It uses the exposed API called "isystem.connect" for controlling/interfacing the winIDEA.
Obtained values exposed the LCD initialization sequence from the ST library for SPFD5408.

Ptyhon script:
import isystem.connect as ic
from isystem.connect import IConnectDebug as ICDebug

    
def toHEX8(val):
  return '0x{0:02X}'.format(val)

def toDEC(val):
  return '{0: 3d}'.format(val)

class LCDInterafceValues:
  def __init__(self):
    self.data = 0
  def setNewValues(self, pinsValues):
    self.data = pinsValues
  def isnCS(self):
    return (self.data & (1<<12)) != 0
  def isRS(self):
    return (self.data & (1<<13)) != 0
  def isnWR(self):
    return (self.data & (1<<14)) != 0
  def isnRD(self):
    return (self.data & (1<<15)) != 0
  def getnCS(self):
    if (self.data & (1<<12)) != 0: return 1
    else: return 0
  def getRS(self):
    if (self.data & (1<<13)) != 0: return 1
    else: return 0
  def getnWR(self):
    if (self.data & (1<<14)) != 0: return 1
    else: return 0
  def getnRD(self):
    if (self.data & (1<<15)) != 0: return 1
    else: return 0
  def getData(self):
    return self.data & 0xFF
  def printHeader(self):
    print "CS  RS  RD  WR  data"
  def printLevels(self):
    if self.isnCS(): print "#  ",
    else: print "|  ",
      
    if self.isRS(): print "#  ",
    else: print "|  ",
  
    if self.isnRD(): print "#  ",
    else: print "|  ",
  
    if self.isnWR(): print "#  ",
    else: print "|  ",
      
    print toHEX8(self.getData()),
    print toDEC(self.getData())
    
cmgr = ic.ConnectionMgr()       # Create a connection manager
cmgr.connectMRU()               # Connect to the last used instance of winIDEA

debug = ic.CDebugFacade(cmgr)   # Create a debug object for the connected winIDEA 
debug.reset()                   # Reset CPU

pv = LCDInterafceValues()       # Create a value parser helper
pv.printHeader()

# Watchpoints have already been set in dialogs in winIDEA
# Just run until a watchpoint is hit, then read the IO levels  
while True:
  debug.run()                   # Run the CPU
  debug.waitUntilStopped()      # Do nothing while the CPU is running
  
  # Evaluate expression. Any C expression with firmware variables would be valid here.
  # '@' prefix tells winIDEA to evaluate (read from memory) a peripheral register.
  PortBPins = debug.evaluate(ICDebug.fMonitor , "@GPIOB_IDR").getInt()
  pv.setNewValues(PortBPins);   # Give the IO port value to helper
  pv.printLevels()              # Display values
 
 
Console output ( '#' means signal is HIGH and '|' that is LOW):
CS  RS  RD  WR  data
#   #   #   #   0x12  18
#   #   #   #   0x12  18
#   #   #   #   0x12  18
#   #   #   #   0x12  18
#   #   #   #   0x12  18
#   |   #   #   0x12  18
|   |   #   #   0x12  18
|   |   #   |   0x12  18
|   |   #   #   0x00   0
|   |   #   |   0x00   0
|   |   #   #   0xE3  227
#   |   #   #   0xE3  227
#   |   #   #   0xE3  227
#   #   #   #   0xE3  227
|   #   #   #   0xE3  227
|   #   #   |   0xE3  227
|   #   #   #   0x30  48
|   #   #   |   0x30  48
|   #   #   #   0x08   8
#   #   #   #   0x08   8
#   #   #   #   0x08   8
#   |   #   #   0x08   8
|   |   #   #   0x08   8
|   |   #   |   0x08   8
|   |   #   #   0x00   0
|   |   #   |   0x00   0
|   |   #   #   0xE7  231
#   |   #   #   0xE7  231
#   |   #   #   0xE7  231
#   #   #   #   0xE7  231
|   #   #   #   0xE7  231
|   #   #   |   0xE7  231
|   #   #   #   0x00   0
|   #   #   |   0x00   0
|   #   #   #   0x12  18
#   #   #   #   0x12  18
#   #   #   #   0x12  18
#   |   #   #   0x12  18
|   |   #   #   0x12  18
|   |   #   |   0x12  18
|   |   #   #   0x00   0
|   |   #   |   0x00   0
|   |   #   #   0xEF  239
#   |   #   #   0xEF  239
#   |   #   #   0xEF  239
#   #   #   #   0xEF  239
|   #   #   #   0xEF  239
|   #   #   |   0xEF  239
|   #   #   #   0x12  18
|   #   #   |   0x12  18
|   #   #   #   0x31  49
#   #   #   #   0x31  49
#   #   #   #   0x31  49



Tuesday, March 6, 2012

STM32F4DISCOVERY Eval board with external debugger

I got the STM32F4DISCOVERY demo board at Embedded World last week. To my surprise the SWD  (single wire debug) connector is not meant for external debugger. In fact it is the other way around. The board can be used  as debugger to debug designs without on-board debugger.

I wanted to attach my debugger anyway. To disable the on-board debugger I hold it in reset by connecting it's reset signal to GND via SB10. To make it reversible I added jumper over SB10 solder jumper.



The external debugger can measure the VDD pin voltage for target detection. *
Single wire output (SWO) trace can be used when using the SWD. * NOTE: this is for trace only - not needed for (invasive) debug.


Even old style JTAG scan debugging is possible (it can be faster) if additional TDI signal is connected. It is at PA15. NOTE: SWO can't be used with JTAG.


Parallel trace on pins PE2 - PE6 is an option when JTAG is used * - not shown on photos.

* -  if supported by external debugger

[Update] See how STM32F4DISCOVERY can be used as free debugger.

Tuesday, January 10, 2012

GCC Assembler for ARM

VMSR and VMRS might not compile with GCC compiler.
One can use FMRX and FMXR instead.

Thursday, December 8, 2011

Kinetis KwikStik upgrade for external debugger

I have modified the KwikStick evaluation board to be able to attach external debugger. Of course connector was soldered. The board has a place for a 1.27mm (50 mil) pitch 10 pin SMD Cortex debug connector. Additionally I have added the jumper to connect integrated J-Link reset line to ground. This way on board debugger will definitely keep it's IOs in state of high impedance.


Wednesday, November 30, 2011

Odd/even value for Cortex M3 reset vector

After reset the CM3 loads it's startup address from address 0x00000004.
The value at that location should be odd (LSB set) denoting the thumb destination. All exception and interrupt vectors following reset vector should be odd.
The reset vector might not have the LSB set by the linker. This is when reset handler code is written in assembler.
It's label is usually used in exception handlers table, but the linker doesn't know that this is a THUMB function address, so it doesn't change the value in exception table. It actually shouldn't since it could be a label of some data table used elsewhere - linker doesn't know anything about exception table either!
We need to tell the linker that some label is a THUMB function. GCC provides '--thumb-entry' command line switch to tell the linker about this one function but I couldn't get it to work. What helped was marking the label as THUMB function with '.type' and/or '.thumb_func' directive - depends on the GCC build/version you are using.


.type Reset, %function
.thumb_func
Reset:
  <code here>

To have some other function exported and available for linkage also add .global for the symbol:

.global Reset

Tuesday, November 29, 2011

Enabling VFP on Cortex R4

Before VFP extension on Cortex can be used, it needs to be enabled.
Following is a C code that does that.
Tested on TMS570 with GCC compiler.
// enable coprocessor 10 and 11 access
asm(" MRC p15,0,R0,c1,c0,2"); // first read CPACR
asm(" ORR R0,R0,#0xF0,16");   // adjust CP10 and CP11 access bits
asm(" MCR p15,0,R0,c1,c0,2"); // write modified CPACR back
asm(" MRC p15,0,R0,c1,c0,2"); // read back - optionally could check:
                              // if 0x00F00000 mask not set the VFP is not present

// When the Security Extensions are implemented,
// the NSACR controls whether each coprocessor can be
// accessed from the Non-secure state

// enable the Advanced SIMD and VFP extensions  
asm(" FMRX R0,FPEXC");      // read FPEXC
asm(" ORR  R0,R0,#0x40,8"); // set EN bit
asm(" FMXR FPEXC,R0");      // write modified value back to FPEXC  

// VFP instruction execution is now allowed
asm(" VMOV S0,R0");

Test post

Welcome!

This is what I do.

This is test post in my new blog about embedded design.