亚洲精品久久久久久久久久久,亚洲国产精品一区二区制服,亚洲精品午夜精品,国产成人精品综合在线观看,最近2019中文字幕一页二页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

調(diào)試 RT-Thread 時(shí),我的代碼怎么“被優(yōu)化”了? | 技術(shù)集結(jié)

RT-Thread官方賬號(hào) ? 2025-10-18 10:34 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

以下是關(guān)于volatile關(guān)鍵的外文描述:

By declaring an object volatile, the compiler is informed that the value of the object can change beyond the compiler’s control. The compiler must also assume that any accesses can have side effects—thus all accesses to the volatile object must be preserved.

There are three main reasons for declaring an object volatile:

Shared access; the object is shared between several tasks in a multitasking environment

Trigger access; as for a memory-mapped SFR where the fact that an access occurshas an effect

Modified access; where the contents of the object can change in ways not known tothe compiler.

1、Shared access

the object is shared between several tasks in a multitasking environment。

當(dāng)同一全局變量在多個(gè)線程之間被共享時(shí),有可能會(huì)出現(xiàn)同步錯(cuò)誤,編譯器可能會(huì)將訪問(wèn)該全局變量的代碼優(yōu)化為訪問(wèn)某個(gè)寄存器,而不會(huì)再次訪問(wèn)相應(yīng)的內(nèi)存,導(dǎo)致程序運(yùn)行錯(cuò)誤。

測(cè)試代碼如下:

staticstructrt_threadv_thread1;
staticcharv_thread1_stack[8192];
staticstructrt_threadv_thread2;
staticcharv_thread2_stack[8192];

staticintflag;
staticintcount;

staticvoidrt_init_thread1_entry(void*parameter)
{
while(1)
{
rt_thread_mdelay(300);
flag=1;
rt_thread_mdelay(300);
flag=0;

if(count++>10)
{
rt_kprintf("thread1 exit.\n");
flag=1;
return;
}
}
}

staticvoidrt_init_thread2_entry(void*parameter)
{
while(1)
{
while(flag==0);
rt_kprintf("thread2 running.\n");
rt_thread_mdelay(100);

if(count++>10)
{
rt_kprintf("thread2 exit.\n");
return;
}
}
}

intvolatile_test()
{
rt_err_tresult=RT_EOK;
result=rt_thread_init(&v_thread1,"vth1",
rt_init_thread1_entry,
RT_NULL,
v_thread1_stack,sizeof(v_thread1_stack),
RT_THREAD_PRIORITY_MAX/3-1,20);
if(result==RT_EOK)
rt_thread_startup(&v_thread1);

result=rt_thread_init(&v_thread2,"vth2",
rt_init_thread2_entry,
RT_NULL,
v_thread2_stack,sizeof(v_thread2_stack),
RT_THREAD_PRIORITY_MAX/3,20);
if(result==RT_EOK)
rt_thread_startup(&v_thread2);

return0;

}
MSH_CMD_EXPORT(volatile_test,runvolatile_test);

上面的測(cè)試代碼在 O0 優(yōu)化時(shí)正常運(yùn)行,打印結(jié)果如下:

msh />volatile_test
thread2 running.
msh />thread2 running.
thread2 running.
thread2 running.
thread2 running.
thread2 running.
thread2 running.
thread2 running.
thread2 running.
thread2 exit.
thread1 exit.

但是如果開(kāi)啟 O3 優(yōu)化,則打印結(jié)果如下:

msh />volatile_test
thread1 exit.

也就是說(shuō) thread2 永遠(yuǎn)得不到運(yùn)行,那么原因是什么呢,請(qǐng)看下圖的反匯編,語(yǔ)句

while(flag==0);

被優(yōu)化成了如下匯編:

00108b4c: ldr r3, [r4, #+288] # 第一次讀取 flag 的實(shí)際值到 r3
00108b50: cmp r3,#0 # 對(duì)比 r3 的值是否為 0
00108b54: bne +0 ; # 如果不為 0 則跳轉(zhuǎn)
00108b58: b -8 ; # 再次跳轉(zhuǎn)回 cmp 語(yǔ)句繼續(xù)循環(huán)

也就是說(shuō),整個(gè)程序被翻譯成,只讀取一次 flag 的實(shí)際值,后續(xù)一直使用 r3 寄存器中的值來(lái)進(jìn)行對(duì)比,而第一次讀取到的 r3 值為零,因此 while 的條件將永遠(yuǎn)成立,thread2 永遠(yuǎn)也得不到執(zhí)行。

2、Trigger access

as for a memory-mapped SFR(特殊功能寄存器)where the fact that an access occurs has an effect。

當(dāng)讀取類似串口設(shè)備的數(shù)據(jù)寄存器時(shí),一定要加上 volatile,因?yàn)樵摰刂芳拇嫫髦械臄?shù)值可能會(huì)發(fā)生改變,如果不加 volatile,可能會(huì)發(fā)現(xiàn)讀取的數(shù)據(jù)是錯(cuò)誤的。

3、Modified access

where the contents of the object can change in ways not known to the compiler.

對(duì)象的內(nèi)容可能會(huì)被以編譯器不清楚的方式被修改,例如在內(nèi)核態(tài)與用戶態(tài)的程序在不同的虛擬地址訪問(wèn)同一塊物理內(nèi)存,此時(shí)如果不加上 volatile,則外部的修改無(wú)法被感知到,造成程序錯(cuò)誤。

關(guān)于優(yōu)化錯(cuò)誤

如果系統(tǒng)在低優(yōu)化等級(jí)能正常運(yùn)行,但是在高優(yōu)化的情況下的無(wú)法正常運(yùn)行,首先懷疑兩個(gè)方面:

是否是一些關(guān)鍵操作沒(méi)有添加 volatile

是否是有內(nèi)存寫穿(因?yàn)椴煌膬?yōu)化等級(jí)改變了內(nèi)存排布導(dǎo)致寫穿位置發(fā)生改變)

4、如何避免關(guān)鍵操作被優(yōu)化

情況一

如果發(fā)現(xiàn)加上了printf打印,或者調(diào)用了某個(gè)外部函數(shù),系統(tǒng)就正常運(yùn)行了,也要懷疑是否出現(xiàn)了變量訪問(wèn)被優(yōu)化的情況,因?yàn)槿绻由狭?strong>外部函數(shù)(非本文件中的函數(shù)或其他庫(kù)中的函數(shù))調(diào)用,則編譯器無(wú)法確定被引用的變量是否被外部函數(shù)所改變,因而會(huì)自動(dòng)從原有地址重新讀取該變量的值。

如果修改上面的測(cè)試代碼,在 while 循環(huán)中加入rt_kprintf打印如下:

while(flag==0)
{
rt_kprintf("5\n");
}

則程序仍然正常運(yùn)行,原因就是編譯器不知道rt_kprintf函數(shù)是否會(huì)修改 flag 變量,因此編譯器會(huì)嘗試每次都重新讀取flag的值。

情況二

還可以使用另外一種方式來(lái)解決這個(gè)問(wèn)題,如下:

while(flag==0)
{
asmvolatile("":::"memory");
}

If our instruction modifies memory in an unpredictable fashion, add "memory" to the list of clobbered registers. This will cause GCC to not keep memory values cached in registers across the assembler instruction. We also have to add thevolatile keywordif the memory affected is not listed in the inputs or outputs of the asm.

這將會(huì)告訴編譯器,經(jīng)過(guò)一些指令后,memory 中的數(shù)據(jù)已經(jīng)發(fā)生了變化,GCC 將不會(huì)再使用寄存器作為數(shù)據(jù)的緩存。因此再次使用這些數(shù)據(jù)時(shí),會(huì)從內(nèi)存中重新嘗試讀取。使用關(guān)鍵字 volatile 也可以達(dá)到同樣的效果。

以下描述摘自《GCC-Inline-Assembly-HOWTO》:

Some instructions clobber some hardware registers. We have to list those registers in the clobber-list, ie the field after the third ’:’ in the asm function. This is to inform gcc that we will use and modify them ourselves. So gcc will not assume that the values it loads into these registers will be valid. We shoudn’t list the input and output registers in this list. Because, gcc knows that "asm" uses them (because they are specified explicitly as constraints). If the instructions use any other registers, implicitly or explicitly (and the registers are not present either in input or in the output constraint list), then those registers have to be specified in the clobbered list.

If our instruction can alter the condition code register, we have to add "cc" to the list of clobbered registers.

4、結(jié)論

關(guān)于 volatile 關(guān)鍵字,最重要的是要認(rèn)識(shí)到一點(diǎn),即是否在編譯器清楚的范圍之外,所操作的變量有可能被改變,如果有這種可能性,則一定要添加上 volatile 關(guān)鍵字,以避免這種錯(cuò)誤。

歸根結(jié)底,是要確定代碼在真實(shí)運(yùn)行的狀態(tài)下,當(dāng)其訪問(wèn)某個(gè)變量時(shí),是否真正地從這個(gè)變量所在的地址重新讀取該變量的值,而不是直接使用上次存儲(chǔ)在某個(gè)寄存器中的值。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5504

    瀏覽量

    128392
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4927

    瀏覽量

    72532
  • RT-Thread
    +關(guān)注

    關(guān)注

    32

    文章

    1509

    瀏覽量

    43922
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    【原創(chuàng)精選】RT-Thread征文精選技術(shù)文章合集

    RT-Thread技術(shù)原創(chuàng)文章精選合集NO1 專欄作者 :矜辰所致簡(jiǎn)介:不浮夸,不將就,認(rèn)真對(duì)待學(xué)知識(shí)的我們,矜辰所致,金石為開(kāi)!畫畫板子敲敲代碼玩玩RTOS搞搞Linux。1. STM32L051
    發(fā)表于 07-26 14:56

    RT-Thread Smart已正式上線,源代碼可下載,采用Apache License 2.0

    官方消息,RT-Thread Smart已正式上線,目前源代碼可在Github、Gitee下載,采用Apache License 2.0。 源碼下載鏈接: https://github.com
    的頭像 發(fā)表于 11-26 14:49 ?3362次閱讀

    記錄——基于 RT-Thread 實(shí)現(xiàn) USB 虛擬串口

    記錄——基于 RT-Thread 實(shí)現(xiàn) USB 虛擬串口記錄一下在正點(diǎn)原子 F429 阿波羅開(kāi)發(fā)板上實(shí)現(xiàn) USB 虛擬串口的過(guò)程,希望可以幫助到其他想要學(xué)習(xí) USB 的人。首先,更新
    發(fā)表于 12-02 17:21 ?6次下載
    記錄——基于 <b class='flag-5'>RT-Thread</b> 實(shí)現(xiàn) USB 虛擬串口

    RT-Thread全球技術(shù)大會(huì):螢石研發(fā)團(tuán)隊(duì)使用RT-Thread技術(shù)挑戰(zhàn)

    RT-Thread全球技術(shù)大會(huì):研發(fā)團(tuán)隊(duì)使用RT-Thread技術(shù)挑戰(zhàn) ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 11:36 ?1780次閱讀
    <b class='flag-5'>RT-Thread</b>全球<b class='flag-5'>技術(shù)</b>大會(huì):螢石研發(fā)團(tuán)隊(duì)使用<b class='flag-5'>RT-Thread</b>的<b class='flag-5'>技術(shù)</b>挑戰(zhàn)

    RT-Thread全球技術(shù)大會(huì):RT-Thread Smart更好的兼容Linux生態(tài)

    RT-Thread全球技術(shù)大會(huì):RT-Thread Smart更好的兼容Linux生態(tài) ? ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 14:31 ?2275次閱讀
    <b class='flag-5'>RT-Thread</b>全球<b class='flag-5'>技術(shù)</b>大會(huì):<b class='flag-5'>RT-Thread</b> Smart更好的兼容Linux生態(tài)

    RT-Thread全球技術(shù)大會(huì):Kconfig在RT-Thread中的工作機(jī)制

    RT-Thread全球技術(shù)大會(huì):Kconfig在RT-Thread中的工作機(jī)制 ? ? ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 14:49 ?2035次閱讀
    <b class='flag-5'>RT-Thread</b>全球<b class='flag-5'>技術(shù)</b>大會(huì):Kconfig在<b class='flag-5'>RT-Thread</b>中的工作機(jī)制

    RT-Thread全球技術(shù)大會(huì):在RT-Thread上編寫測(cè)試用例

    RT-Thread全球技術(shù)大會(huì):在RT-Thread上編寫測(cè)試用例 ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 16:28 ?1906次閱讀
    <b class='flag-5'>RT-Thread</b>全球<b class='flag-5'>技術(shù)</b>大會(huì):在<b class='flag-5'>RT-Thread</b>上編寫測(cè)試用例

    RT-Thread全球技術(shù)大會(huì):RT-Thread測(cè)試用例集合案例

    RT-Thread全球技術(shù)大會(huì):RT-Thread測(cè)試用例集合案例 ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 16:34 ?2590次閱讀
    <b class='flag-5'>RT-Thread</b>全球<b class='flag-5'>技術(shù)</b>大會(huì):<b class='flag-5'>RT-Thread</b>測(cè)試用例集合案例

    RT-Thread全球技術(shù)大會(huì):RT-Thread對(duì)POSIX的實(shí)現(xiàn)情況介紹

    RT-Thread全球技術(shù)大會(huì):RT-Thread對(duì)POSIX的實(shí)現(xiàn)情況介紹 ? ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 16:52 ?2325次閱讀
    <b class='flag-5'>RT-Thread</b>全球<b class='flag-5'>技術(shù)</b>大會(huì):<b class='flag-5'>RT-Thread</b>對(duì)POSIX的實(shí)現(xiàn)情況介紹

    RT-Thread全球技術(shù)大會(huì):在RT-Thread中使用棧幀來(lái)調(diào)試程序

    百問(wèn)網(wǎng)科技CTO韋東山,在RT-Thread全球技術(shù)大會(huì)大會(huì)中,以在RT-Thread中使用棧幀來(lái)調(diào)試程序?yàn)橹黝}進(jìn)行了介紹。
    的頭像 發(fā)表于 05-28 09:33 ?2288次閱讀
    <b class='flag-5'>RT-Thread</b>全球<b class='flag-5'>技術(shù)</b>大會(huì):在<b class='flag-5'>RT-Thread</b>中使用棧幀來(lái)<b class='flag-5'>調(diào)試</b>程序

    RT-Thread 編程風(fēng)格

    作者:架構(gòu)師李肯 前言 最近博主在學(xué)習(xí) RT-Thread 這個(gè)開(kāi)源項(xiàng)目,開(kāi)始慢慢學(xué)習(xí)和理解它的開(kāi)源代碼,慢慢開(kāi)始接觸它的代碼規(guī)范。 個(gè)
    的頭像 發(fā)表于 12-06 19:55 ?1712次閱讀

    RT-Thread文檔_RT-Thread 簡(jiǎn)介

    RT-Thread文檔_RT-Thread 簡(jiǎn)介
    發(fā)表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡(jiǎn)介

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    使用RT-Thread Studio進(jìn)行智能家居終端的設(shè)計(jì)

    本次方案基于星火一號(hào)開(kāi)發(fā)板開(kāi)發(fā),使用RT-Thread Studio進(jìn)行工程創(chuàng)建,代碼編輯,RT-Thread配置,調(diào)試配置,程序下載等功能。
    的頭像 發(fā)表于 07-28 16:41 ?2624次閱讀
    使用<b class='flag-5'>RT-Thread</b> Studio進(jìn)行智能家居終端的設(shè)計(jì)

    RT-Thread v5.0.2 發(fā)布

    RT-Thread 代碼倉(cāng)庫(kù)地址: ●? https://github.com/RT-Thread/rt-thread RT-Thread
    的頭像 發(fā)表于 10-10 18:45 ?2475次閱讀
    <b class='flag-5'>RT-Thread</b> v5.0.2 發(fā)布