ST意法半导体
直播中

李华

8年用户 1439经验值
私信 关注
[问答]

如何在C程序中编写汇编代码以打开/关闭GPIO引脚?

大家好,我正在尝试测量完成执行一个功能所用的时间。我不能使用定时器,因为它会给系统增加一些延迟。我的另一个选择是使用 GPIO 引脚。
为此,我
在函数的开头设置一个引脚
在函数末尾重置一个引脚
然后我使用示波器测量引脚的开关时间。
为了在没有太多延迟的情况下打开和关闭 GPIO,我使用了汇编代码来确保仅使用几条指令来启用和禁用 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
  •         );
  • }
然而生成的代码看起来像下图...

使用此生成的代码,示波器的 GPIO 引脚产生了一个宽度不同的脉冲,如下图所示

从我上面的汇编代码来看,脉冲宽度应该或多或少相同,因为我每个周期运行相同数量的指令。但我不知道为什么我不能让编译器遵循我在 C 程序中编写的汇编代码。
最终,我试图实现一个非常轻的代码来打开/关闭 gpio 引脚,以便我可以准确地测量一个函数所花费的时间。我试图实现的代码如下所示
  • 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
  • );
  • }
最后,我的编译器设置为 Optimization Fast,我使用的是 Atollic Truestudio。系统中只有一个中断,即 ADC 转换完成。
如果您需要任何其他信息,请告诉我。谢谢阅读!
EDIT1:有谁知道为什么编译后的汇编代码与我的内联汇编代码不同?我希望这部分汇编代码不要被编译器优化触及/修改,同时仍然使用优化速度选项。









回帖(1)

闫雪花

2023-1-12 11:35:11
GPIOE->BSRR = GPIO_BSRR_BS_2;
...
GPIOE->BRR = GPIO_BSRR_BR_2;
举报

更多回帖

发帖
×
20
完善资料,
赚取积分