cancel
Showing results for 
Search instead for 
Did you mean: 

Writing assembly code in a C program to turn On/Off GPIO pin

Xxoyo.1
Associate III

Hello everyone, I am trying to measure how much time is used to finish executing a function. I cannot use the timers because it adds some delay to the system. My other option is to use GPIO pins.

To do this, I

SET a pin at the start of the function

RESET a pin at the end of the function

I then use an oscilloscope to measure the on off time of the pin.

In order to turn on and off the GPIO without too much delay, I have used assembly code to ensure just a few instructions are used for enable and disable the GPIO.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)		//called every 4 us.
{
	__asm__ volatile (
			//turn on GPIO E2
"LDR		R1,		=0x40021014;"
"LDR		R0,	[R1];"
"ORR.W		R0,	#0x0004;"	//only set pin 2
"STR		R0,	[R1];"		//write data to memory
 
			//write data to data memory
"LDR		R3,		=0xD0007260;"
"LDR		R2,	[R3];"
"LDR   		R2,=0xFF000000;"
"STR		R2,	[R3];"		//write data to memory
 
 
			//turn off  GPIO E2
//"LDR		R5,		=0x40021014;"
//"LDR		R4,	[R5];"
"AND.W		R0,  #0xFFFFFFFB;"	//only clear pin 2
"STR		R0,  [R1];"			//write data to memory
	);
 
 
 
}

However the generated code looks like the image below...

0693W000005CEd6QAG.png 

Using this generated code, the GPIO pin to the Oscilloscope produced a pulse with varying width as shown in the image below

0693W000005CEbyQAG.pngFrom my assembly code above, the pulse width should be more or less identical since I am running the same number of instructions each cycle. But I do not know why I cannot get the compiler to follow the assembly code that I wrote in my C program.

Ultimately, I am trying to achieve a very light code to turn on/off the gpio pin so that I can accurately measure the time taken by a function. The code I am trying to achieve would be like the following

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)		//called every 4 us.
{
 
//read GPIO E ODR address
__asm__ (
	"LDR		R1,		=0x40021014;"
	"LDR		R0,	[R1];"
);
 
//Turn on GPIO E2
__asm__ (
	"ORR.W		R0,	#0x0004;"	//only set pin 2
	"STR		R0,	[R1];"		//write data to memory
);
 
 
//example function 
BSP_LCD_DrawPixel(120, 60, LCD_COLOR_BLACK);
 
// Turn off GPIO E2
__asm__ (
		"AND.W		R0,  #0xFFFFFFFB;"	//only clear pin 2
		"STR		R0,  [R1];"			//write data to memory
);
 
}

Lastly, my compiler is set to Optimization Fast and I am using Atollic Truestudio. I only have one Interrupt in the system which is the ADC conversion complete.

If you need any other information, pls let me know. Thanks for reading!

EDIT1: Does anyone know why the compiled Assembly code is not the same as my inline assembly code? I would prefer this part of assembly code to not be touched /modified by compiler optimization while still using the optimize for speed option.

10 REPLIES 10

Thank you for your quick reply, upon inspection in another datasheet

https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

I have found that the cortex-m4 does support DWT debug. And thank you for your code, it is very helpful for me !

I have successfully read DWT->CYCCNT. Lastly, I need to multiply with 1/MCU Frequency to get the time in seconds.