Semihosting on the STM32F042 Nucleo board

The STM32F042 Nucleo board is a nice, low cost development board that is suitable for breadboard based development.  It includes an STLink-V2 debug interface which allows semihosting when used in conjunction with OpenOCD.
Semihosting allows a program send debug messages back to a host during development. It is of little use as a general communications interface as the processor simply stops running if the host is not attached (and running openocd or equivalent). Its main use however is to help you diagnose tricky faults during development. I decided to use it to trap unhandled interrupts which were generated by writing to a bad memory address as shown below:

unsigned *BadMemoryAddress;
:
:
// Point at a known bad memory address (reserved/unconnected space)
	BadMemoryAddress = (unsigned *)0xfffffffc;
:
// Generate a hard fault (exception number 3)
// by writing to a bad memory address
	*BadMemoryAddress = 42;

For my implementation, the Hard Fault interrupt vector simply pointed to a default handler which is shown here:

void Default_Handler(void)
{
// Reference: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Babefdjc.html 
// Note: Using a different compiler or changing compiler options may change the stack ordering
/* Stack on entry:
 * 	xPSR				offset 44
 * 	PC					offset 40
 *	LR					offset 36
 * 	R12					offset 32
 * 	R3					offset 28
 * 	R2					offset 24
 * 	R1					offset 20
 * 	R0					offset 16
 * 	FramePointer		offset 12
 * 	LR					offset 8
 * 	local variable 1	offset 4
 * 	local variable 2	offset 0
 * 
 */
	unsigned status;
	unsigned stackpointer;
	// Read the contents of the IPSR register 
	// This should contain the exception number
	asm("mrs %[status], ipsr \r\n"
	 : [status]"=rm"(status)
	 :
	 :
	 );
	asm("mov %[stackpointer],sp \r\n"
	 : [stackpointer]"=rm"(stackpointer)
	 :
	 :
	 );
	debug_printString("\r\nUnhandled exception.\r\nIPSR =  ");
	debug_printInteger(status);
	debug_printString("\r\nLast instruction location = ");	
	debug_printInteger(*(unsigned *)(stackpointer+40));
	// while(1);  Uncomment this if you want to processor to stop here.
	
}

This code outputs the Interrupt Program Status Register (IPSR) contents to openocd (you will see it in the console where openocd was invoked) as well as the value of the Program Counter when the exception/interrupt occurred. The IPSR register contains the exception number which should be 3 for a hard fault like this.
The debug_printString and debug_PrintInteger functions are provided in the source code which is available at
http://eleceng.dit.ie/frank/arm/BareMetalSTM32F042Nucleo/index.html

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s