1、volatile關鍵字
volatile 是易變的、不穩定的意思。 和const一樣是一種類型修飾符,volatile關鍵字修飾的變量,編譯器對訪問該變量的代碼不再進行優化,從而可以提供對特殊地址的穩定訪問。
以前只是聽過這個關鍵詞,知道它的存在,但從來沒用過。 用此文記錄下在開發RISC-V MCU過程中,未用volatile修飾標志位變量,編譯器進行優化,導致程序運行異常。
2、演示
開發中,常見的需求,主循環中根據中斷中修改的標志位,運行不同的功能,
#include "debug.h"
uint8_t flag_interrupt = 0;
int main(void)
{
USART_Printf_Init(115200);
printf("SystemClk:%d\\r\\n",SystemCoreClock);
EXTI0_INT_INIT();
while(1)
{
if(flag_interrupt == 1)
{
flag_interrupt = 0;
printf("do something\\r\\n");
}
}
}
/* 外部中斷服務函數*/
__attribute__((interrupt("WCH-Interrupt-fast")))
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)==SET) //EXTI_GetITStatus用來獲取中斷標志位狀態
{
flag_interrupt = 1;
printf("Run at EXTI\\r\\n");
EXTI_ClearITPendingBit(EXTI_Line0); //清除中斷標志位
}
}
進入中斷服務函數,改變了flag_interrupt的值,但是主函數仍然沒有運行相應的程序,很是奇怪,檢查反匯編代碼,才發現是編譯器對flag_interrupt變量的訪問進行了優化,如圖,將程序下載至MCU后,給P1.0引腳下降沿觸發信號,運行現象如下
278: 01271063 bne a4,s2,278 0x34> # 不相等就跳轉至0x278的位置,即還是本條語句的位置,
可以看到,編譯器對flag_interrupt變量的訪問進行了優化,沒有重新去0x20000080的位置進行取值,而是每次都用a4寄存器的值與s2寄存器(值為1)比較,不相等還是跳回本條語句的位置,重復運行,導致即使在中斷中改變了其值,主循環中也不能運行對應的功能。 這時候就需要使用volatile關鍵字對flag_interrupt進行修飾。
volatile uint8_t flag_interrupt = 0;
加了volatile關鍵字修飾flag_interrupt后,程序按照設定的預期運行,如下圖所示:
查看反匯編代碼,編譯器未對flag_interrupt變量進行優化,老老實實的每次去源地址0x20000080處取值訪問。
-
中斷
+關注
關注
5文章
900瀏覽量
41753 -
代碼
+關注
關注
30文章
4827瀏覽量
69054 -
編譯器
+關注
關注
1文章
1642瀏覽量
49286 -
關鍵字
+關注
關注
0文章
37瀏覽量
6926 -
volatile
+關注
關注
0文章
45瀏覽量
13062
發布評論請先 登錄
相關推薦
評論