當(dāng)前位置:首頁 > 公眾號(hào)精選 > 嵌入式大雜燴
[導(dǎo)讀]關(guān)注「嵌入式大雜燴」,星標(biāo)公眾號(hào),一起進(jìn)步!來源:裸機(jī)思維【說在前面的話】相信很多人都遇到過這樣的情況:在一個(gè)Cortex-M嵌入式應(yīng)用中要實(shí)現(xiàn)一個(gè)精確的毫秒級(jí)延時(shí)并不困難——如果你有RTOS,在任務(wù)中使用諸如os_sleep()之類的函數(shù)就可以輕松實(shí)現(xiàn);如果你是裸機(jī),也可以使用...

關(guān)注「嵌入式大雜燴」,星標(biāo)公眾號(hào),一起進(jìn)步!

來源:裸機(jī)思維


【說在前面的話】

相信很多人都遇到過這樣的情況:在一個(gè)Cortex-M嵌入式應(yīng)用中要實(shí)現(xiàn)一個(gè)精確的毫秒級(jí)延時(shí)并不困難——如果你有RTOS,在任務(wù)中使用諸如 os_sleep(<休眠時(shí)間>) 之類的函數(shù)就可以輕松實(shí)現(xiàn);如果你是裸機(jī),也可以使用每個(gè)Cortex-M芯片都默認(rèn)攜帶的SysTick來實(shí)現(xiàn)一個(gè),甚至Arm官方的CMSIS都提供了現(xiàn)成的API,即SysTick_Config(<中斷間隔的時(shí)鐘周期數(shù)>)
static volatile uint32_t s_wMSCounter = 0;
extern?uint32_t?SystemCoreClock;/*! \brief initialise platform before main() */__attribute__((constructor(101)))void platform_init(void){ SystemCoreClockUpdate(); /* Generate interrupt each 1 ms */ SysTick_Config(SystemCoreClock / 1000); }
__attribute__((weak))void systimer_1ms_handler(void){????/*?default?systimer?1ms?hander??????*?you?can?override?it?by?implement?a?non-weak version?????*/}
void SysTick_Handler (void) { if (s_wMSCounter) { s_wMSCounter--; }
systimer_1ms_handler();}
void delay_ms(uint32_t wMillisecond){ s_wMSCounter = wMillisecond; while( s_wMSCounter > 0 );}上述代碼非常典型,唯一需要強(qiáng)調(diào)的是SystemCoreClock是一個(gè)定義在啟動(dòng)文件system_<芯片型號(hào)>.c 里的全局變量,負(fù)責(zé)保存當(dāng)前處理器的工作頻率——上面的平臺(tái)初始化函數(shù) platform_init()?就是借助這一變量把 SysTick 初始化為以“1ms為間隔產(chǎn)生中斷”的。

如果要實(shí)現(xiàn)一個(gè)微秒級(jí)延時(shí)卻并不那么一帆風(fēng)順。首先,不同人關(guān)于實(shí)現(xiàn)方案就有不同的想法,比如:
  • 有的人習(xí)慣于直接用軟件方法堆積NOP()來實(shí)現(xiàn)——這種方法所產(chǎn)生的延時(shí)效果“可能”容易受到編譯器優(yōu)化等級(jí)的影響——據(jù)說這也是很多人懼怕開啟編譯器的原因之一,因?yàn)橐婚_優(yōu)化,很多對(duì)時(shí)間敏感的硬件時(shí)序就因?yàn)檠訒r(shí)函數(shù)的不穩(wěn)定而一起變得不可捉摸;

extern?uint32_t?SystemCoreClock;
#ifndef DELAY_US_CALIBRATION/*!?\brief?不要問我為啥是?8, 我也不知道,但在當(dāng)前這個(gè)工程下,8貌似最準(zhǔn)?*!????????你如果不服,就自己測(cè)一個(gè),然后定義這個(gè)宏……?*!????????如果你頭鐵改了工程的優(yōu)化等級(jí),請(qǐng)也無比親自測(cè)一下……具體怎么?*! ???????測(cè),我也不知道。如果你也怕麻煩,就不要改優(yōu)化等級(jí)。 */# define DELAY_US_CALIBRATION 8#endif
void?delay_us(uint32_t?wUS){????//!?calcluate?how?many?cycles?required?for?1us????uint32_t?wCyclesPerUS?=?SystemCoreClock?/?1000000ul;????????/*!?subtract some cycles from wCyclesPerUS based on the ?????*!?experience?or?actual?measurement?in?current?optimisation?????*/????wCyclesPerUS?-=?DELAY_US_CALIBRATION;
????for?(int?i?=?0;?i?????????for?(j?=?0;?j?< wCyclesPerUS; j ) {???????? __NOP();????????}????}}
  • 有的人提倡使用定時(shí)器來實(shí)現(xiàn)精確延時(shí),這一方案顯然不太懼怕編譯器優(yōu)化的“血腥巨斧”。想法是沒錯(cuò)的,但如果要保證這樣寫出來的延時(shí)庫有一定的可移植性,就需要保證 delay_us() 函數(shù)實(shí)現(xiàn)所依賴的硬件定時(shí)器是“通用的”和“普遍存在”的——符合這一要求的第一選擇是SysTick——然而既然SysTick已經(jīng)被 delay_ms() 占用了,又如何能抽的開身呢?


既然 SysTick 被占用了,那有沒有別的符合要求的硬件呢?如果不算Cortex-M0/M0 的話,從某種程度上說還真有——DWT。這是一個(gè)系統(tǒng)外設(shè),專門用來為Cortex-M3及其以上芯片提供調(diào)試和追蹤的硬件輔助功能。在【裸機(jī)思維】往期轉(zhuǎn)載的文章中,就有使用DWT實(shí)現(xiàn)延時(shí)的內(nèi)容。這個(gè)方法好是好,但缺點(diǎn)也是非常突出的:
  • DWT 根本就不是設(shè)計(jì)給用戶用的,它是Cortex-M處理器預(yù)留給上位機(jī)調(diào)試軟件(例如MDK)進(jìn)行調(diào)試和追蹤的。換句話說,上位機(jī)調(diào)試軟件覺得這是自己的私人財(cái)產(chǎn),從來沒想過用戶會(huì)去使用它——這就導(dǎo)致調(diào)試過程中,IDE會(huì)按照自己的意思隨意修改它的配置——啥時(shí)候會(huì)改呢?這要看IDE的心情。如果你的程序依賴了DWT進(jìn)行延時(shí),那么調(diào)試的時(shí)候,IDE的一個(gè)無心之舉可能就會(huì)毀了你的時(shí)序——這一知識(shí)點(diǎn)非常容易忽略掉,從而導(dǎo)致很多人遇到調(diào)試的時(shí)候,系統(tǒng)隨機(jī)性的功能不正常的坑,從而浪費(fèi)大把的時(shí)間,往往還想不到是DWT導(dǎo)致的——說這一方法是天坑可能一點(diǎn)也不為過。

  • DWT 不是所有 Cortex-M 芯片都有……(Cortex-M0/M0 就沒有)


既然 SysTick 被占用、DWT?又是天坑,是不是意味著我們就只能使用芯片的普通定時(shí)器了?——這每個(gè)廠家都不一樣……每個(gè)應(yīng)用對(duì)定時(shí)器的使用情況也都不同,那我還怎么做通用的延時(shí)庫???

別急,今天我們就來介紹一種在完全不影響 SysTick 已有功能的前提下,繼續(xù)把它榨干——提供更多功能的方法。為了避免誤解,我把這種方法的目標(biāo)需求列舉如下:
  • 提供一個(gè)精確的 delay_us() 函數(shù);

  • 提供一個(gè)精確測(cè)量任意代碼塊所實(shí)際占用系統(tǒng)周期數(shù)的方法;

  • 實(shí)現(xiàn)一個(gè)記錄從進(jìn)入 main() 函數(shù)以來總共經(jīng)歷了多少個(gè)時(shí)鐘周期(且在合理的時(shí)間范圍內(nèi)不會(huì)溢出)的計(jì)數(shù)器(時(shí)間戳);

  • 用戶已有的 SysTick 功能不能受到干擾;

    • 比如用戶使用 SysTick 作為RTOS的基準(zhǔn)時(shí)鐘(非Tickless模式);

    • 比如用戶使用 SysTick 作為普通的毫秒級(jí)延時(shí)(就像前面例子代碼所展示的那樣);

  • 用戶不需要修改自己任何已有的 SysTick 代碼。



【部署 perf_counter 庫】

要實(shí)現(xiàn)上述功能,可以直接借助一個(gè)叫做 perf_counter 的庫,這是我基于這幾年在代碼性能分析中總結(jié)出來的,我已經(jīng)把它放在 github 上進(jìn)行開源,其地址為:https://github.com/GorgonMeducer/perf_counter
這個(gè)庫目前支持 Arm Compiler 5(armcc) 和 Arm Compiler 6(armclang)。它不僅提供了源代碼,還提供了編譯好的 library (.lib)可供全系列Cortex-M處理器使用。
第一步,下載最新的release:


解壓縮后可以看到如下的內(nèi)容:

如果只是普通的使用,直接拷貝 lib 目錄到你的工程即可。


第二步,將庫加入到已有的 MDK 工程中:



別忘記在工程的頭文件搜尋路勁中包含 perf_counter.h 所在文件夾,例如(具體位置根據(jù)你工程的情況而定,不要死腦經(jīng)):



第三步:編譯并調(diào)整一些工程選項(xiàng)

如果你編譯后很順利,則請(qǐng)?zhí)^下面的內(nèi)容,快進(jìn)到 0 error 0 warning的圖片之后。



好,下面讓我們來談?wù)勀憧赡苡龅降膯栴},以及對(duì)應(yīng)的解決方案:


問題一:提示找不到 $Super$$SysTick_Handler

.\Out\example.axf: Error: L6218E: Undefined symbol $Super$$SysTick_Handler (referred from systick_wrapper_ual.o).Not enough information to list image symbols.Not enough information to list load addresses in the image map.Finished: 2 information, 0 warning and 1 error messages.".\Out\example.axf" - 1 Error(s), 0 Warning(s).

perf_counter 庫是一個(gè)“附加型”庫——它假設(shè)你自己已經(jīng)實(shí)現(xiàn)了一個(gè)SysTick的中斷處理程序,并開啟了中斷模式——如果你沒有,直接加一個(gè)空的就好了:

void SysTick_Handler (void) {}好,問題解決。什么?你的工程也根本沒有用SysTick?好辦,請(qǐng)?jiān)?span>進(jìn)入main后調(diào)用函數(shù)init_cycle_counter()?并傳遞false,例如:

int main(void){ ... init_cycle_counter(false); ...}這樣做的目的是告訴 perf_counter:“請(qǐng)自己玩的開心”。


問題二:wchar和enum的尺寸不兼容:

需要強(qiáng)調(diào)的是,perf_counter.lib 庫在編譯的時(shí)候,開啟了 Short enums/wchar(分別對(duì)應(yīng)命令行的?-fshort-enums -fshort-wchar)。這么做其實(shí)沒什么特別的原因,但如果你的工程使用了不同的配置,例如:


下圖的工程配置中,沒有勾選 "Short enums/wchar"


你一定會(huì)看到這樣的編譯錯(cuò)誤:

.\Out\example.axf: Error: L6242E: Cannot link object perf_counter.o as its attributes are incompatible with the image attributes. ... wchart-16 clashes with wchart-32. ... packed-enum clashes with enum_is_int.

既然知道了原因,解決方法就很簡單,要么在工程配置中勾選上這一選項(xiàng);要么使用源代碼編譯(不使用lib):



也就是圖中所示的:perf_counter.c systick_wrapper_ual.s。


? ? perf_counter.c 依賴了 CMSIS,所以確保你的工程中加入了對(duì)CMSIS的支持——推薦的是使用MDK自帶的 CMSIS,在RTE配置界面中勾選:



如果你使用的是工程自帶的CMSIS(很多STM32工程就是這樣),請(qǐng)確保你的CMSIS?是較新的版本(判斷標(biāo)準(zhǔn)就是是否帶有 cmsis_compiler.h)。


此外,這里的 systick_wrapper_ual.s 是一個(gè)匯編源程序,使用的是Arm的老語法(Unified Assembly Language),如果你的工程使用的是 Arm Compiler 5(armcc),這里就沒什么需要特別注意的了;如果你的工程使用的是 Arm Compiler 6(armclang),則你需要檢查工程配置,以確保MDK能正確的選擇對(duì)應(yīng)的Assembler


注意這里的 Assembler Option,根據(jù)你MDK版本的不同,它可能有以下幾個(gè)有效選項(xiàng):
  • armclang(Auto Select)——我吐血推薦選這個(gè)

  • armclang(GNU Syntax)——?這個(gè)意思就是使用 GNU的匯編語法,顯然不能選它;

  • armclang(Arm Syntax)——這是最新MDK(從5.32開始)才有的選項(xiàng),選了也行;

  • armasm(Arm Syntax)——這就是 Arm Compiler 5里一直使用的老匯編器,選他當(dāng)然兼容性最好。


做好了以上兩個(gè)準(zhǔn)備工作,編譯應(yīng)該就很順利了。是不是覺得有點(diǎn)頭大?頭大就用?.lib 啊……完全不用經(jīng)歷這些痛苦。




至此,我們完成了 perf_counter 庫在工程中的部署。那么它帶給我們哪些功能呢?


【SysTick第一吃:微秒級(jí)精確延時(shí)】


#include?"perf_counter.h"
...delay_us(30);????//!...

再也不用擔(dān)心編譯器優(yōu)化導(dǎo)致延時(shí)不準(zhǔn)啦?。。?br>

再也不擔(dān)心庫不通用啦?。?!

再也不用擔(dān)心芯片不支持DWT啦?。。。。。?/span>

再也不用擔(dān)心調(diào)試/追蹤會(huì)干擾DWT啦!!??!





【SysTick第二吃:精確測(cè)量代碼的時(shí)鐘周期】

perf_counter.h 提供了兩個(gè)函數(shù),用于精確測(cè)量任意代碼片段所消耗的CPU時(shí)鐘周期數(shù)(不是us數(shù)哦):
extern void start_cycle_counter(void);extern int32_t stop_cycle_counter(void);它們的使用非常簡單直接,例如:
start_cycle_counter();//!?測(cè)量?打印??"Hello?World\r\n" 究竟用了多少個(gè)時(shí)鐘周期printf("Hello World! \r\n");int32_t?iCycleUsed?=?stop_cycle_counter(void);printf("Cycle?Used:?%d",?iCycleUsed);當(dāng)然,如果你的工程環(huán)境允許你用printf的話,還可以用 perf_counter.h 自帶的宏將上述代碼簡化一下:

//!?the?demo?of?__cycleof__()__cycleof__() {????printf("Hello?World\r\n");}其運(yùn)行結(jié)果為:

(以上結(jié)果為FVP仿真結(jié)果,CPU周期數(shù)值不可以做參考)


我們甚至還可以添加一點(diǎn)注釋性的字符串,幫助我們區(qū)分測(cè)試的范圍:

//!?the?demo?of?__cycleof__()__cycleof__("Print?string")?{????printf("Hello?World\r\n");}

我們看到,傳遞給__cycleof__的提示字符串"Print string"被添加到了"total cycle count:..." 的前面,一目了然。


實(shí)際上,start_cycle_counter()stop_cycle_counter() 的組合還可以用來測(cè)量中斷處理程序?qū)嶋H使用的系統(tǒng)周期數(shù)——讀過我【實(shí)時(shí)性迷思】系列文章的小伙伴,一定知道測(cè)量“事件處理函數(shù)所需時(shí)間”的意義:

volatile?int32_t?g_nMaxHandlingCycles = 0;
void?USART0_RX_Handler(void){????start_cycle_counter();????????//!?你的USART0 接收中斷處理程序?qū)嶋H內(nèi)容????...????????int32_t nCycles = stop_cycle_counter();????g_nMaxHandlingCycles?=?MAX(nCycles,?g_nMaxHandlingCycles);}

從此一舉告別“拍腦袋憑感覺”說中斷處理時(shí)間要多長的舊世界。


此外,start_cycle_counter()?和 stop_cycle_counter() 還支持類似體育老師所使用的秒表的功能,即,起跑后、可以分別記錄每一個(gè)學(xué)生所用的時(shí)間。具體表現(xiàn)為:

int32_t nCycles = 0;start_cycle_counter();???? //!...nCycles?=?stop_cycle_counter();??//!...nCycles?=?stop_cycle_counter();??//!...nCycles?=?stop_cycle_counter();??//!< 第三次獲取從開始以來的時(shí)間...具體什么情況下要用到這樣的方式就見仁見智了,這里就不再繼續(xù)展開。


最后,需要強(qiáng)調(diào)一下,雖然 start_cycle_counter()stop_cycle_counter()startstop 的字樣,但這只是邏輯上的,并不會(huì)真正的干擾 SysTick 的功能(也就是不會(huì)開啟或者關(guān)閉 SysTick)。這也是這個(gè)庫敢于聲稱自己不會(huì)影響用戶已有的 SysTick 功能的原因。

【SysTick第三吃:系統(tǒng)時(shí)間戳】

閱讀到這里,聰明的你一定已經(jīng)發(fā)現(xiàn)了:無論是 perf_counter(performance counter)庫名的明示,還是 start_cycle_counter()stop_cycle_counter() 的強(qiáng)大功能,都暗示其實(shí)這個(gè)庫應(yīng)該不是專門用來提供微秒延時(shí)函數(shù) delay_us() 的,實(shí)際上,只要你稍微看一眼源代碼就會(huì)發(fā)現(xiàn)上述猜想完全沒錯(cuò)—— delay_us() 其實(shí)才是附贈(zèng)的:
void delay_us(int32_t iUs){ iUs *= SystemCoreClock / 1000000ul; start_cycle_counter(); while(stop_cycle_counter() < iUs);}

看到真相的你,有沒有意識(shí)到,在 start_cycle_counter()stop_cycle_counter() 之間不能調(diào)用 delay_us() 呢?

既然 delay_us() 都是“cycle counter”送的,還有啥別的功能是附贈(zèng)的么?——還真有:系統(tǒng)時(shí)間戳。想象一下,既然 start_cycle_counter()stop_cycle_counter() 的組合可以獲得從開始以來的時(shí)間,那么如果我在進(jìn)入main()之前就執(zhí)行 start_cycle_counter() ,然后在需要的時(shí)候調(diào)用 stop_cycle_counter() 是不是就可以獲取“從main()開始已經(jīng)執(zhí)行了多少個(gè)周期”的系統(tǒng)時(shí)間戳呢?
Bingo!答對(duì)了,原理上就是這樣,只不過實(shí)際上,為了保留 start_cycle_counter() stop_cycle_counter() 給用戶使用,per_counter庫就自己獨(dú)立實(shí)現(xiàn)了對(duì)應(yīng)的邏輯——用戶可以通過調(diào)用函數(shù)?clock() 來獲取這一信息:
#ifdef __PERF_CNT_USE_LONG_CLOCK____attribute__((nothrow)) extern int64_t clock(void);#endif熟悉系統(tǒng)庫 朋友可能會(huì)立即產(chǎn)生疑問,真正的定義不應(yīng)該是這樣的么:
extern _ARMABI clock_t clock(void);clock_t 在 Cortex-M環(huán)境下定義如下:

typedef unsigned int clock_t; /* cpu time type */為什么perf_counter.h 要采用不一樣的定義呢?


說起來也簡單:clock() 函數(shù)返回的是系統(tǒng)周期數(shù),而不是什么以 us 或者 ms 為單位的時(shí)間——考慮到現(xiàn)在處理器頻率動(dòng)輒幾百兆赫茲,有的甚至達(dá)到了1GHz(比如 NXP的RT系列),如果用 int32_t?(哪怕用 uint32_t)也撐不了幾秒鐘。


假設(shè)系統(tǒng)頻率為1GHz,使用 uint32_t 來計(jì)數(shù),由于32bit整數(shù)取值范圍是0~4G,因此,最多4秒就撐不住了……


那究竟多長才夠呢?



當(dāng)我們使用 int64_t 的時(shí)候,哪怕系統(tǒng)頻率是 4GHz,2G 秒 ≈ 24855 天 ≈ 68年。雖然沒有一萬年那么久,不過多半一個(gè)嵌入式設(shè)備也沒法用這么久(千年蟲警告),但考慮到大部分Cortex-M嵌入式系統(tǒng)估計(jì)沒有4GHz這么夸張,輕松跑個(gè)1000多年不溢出應(yīng)該是沒有問題的。


既然我們鐵了心要用 int64_t 來取代 clock_t 原本的 int32_t,怎么解決這里的沖突呢?——顯然去修改系統(tǒng)頭文件 是不允許的!


翻開Arm的隱藏寶典:AAPCS,我們發(fā)現(xiàn)以下的規(guī)則:

32位系統(tǒng)下,

  • 如果函數(shù)的返回值其大小不超過32bit,則保存在寄存器 r0中;

  • 如果函數(shù)的返回值其大小為64bit,則其低 32bit 保存在 r0中、高32bit保存在 r1中。


顯然,當(dāng)我們實(shí)現(xiàn)clock()函數(shù)時(shí)返回 int64_t的值與 返回 int32_t其實(shí)是兼容的——因?yàn)榈?em>32bit的內(nèi)容實(shí)際上都是保存在 r0 里的,此時(shí)如果用戶調(diào)用clock() 的時(shí)候:

  • 使用的是里定義的函數(shù)原型,即? clock_t clock(void),則,當(dāng)函數(shù)返回時(shí),r1里保存的值會(huì)被無視,只有r0里的值被視作返回值;

  • 使用的是我們自己定義的函數(shù)原型,即 int64_t clock(void),則你可以獲得完整的 int64_t 時(shí)間戳。


既然原理清楚了,再看 perf_counter.h 里面的定義,我們會(huì)發(fā)現(xiàn)clock()的函數(shù)原型被一個(gè)宏?__PERF_CNT_USE_LONG_CLOCK__ 保護(hù)著:

#ifdef __PERF_CNT_USE_LONG_CLOCK____attribute__((nothrow)) extern int64_t clock(void);#endif這實(shí)際上是告訴我們,如果我們想獲得 int64_t 時(shí)間戳?xí)r,只要在工程中定義宏??__PERF_CNT_USE_LONG_CLOCK__?就可以了。



忙活了半天,有的小伙伴可能會(huì)疑惑了:饒了這么一大圈,clock() 究竟有啥用處呢?這玩法就多了,快一鍵三聯(lián)~ 下次我們好好來說說。



【后記】

perf_counter(https://github.com/GorgonMeducer/perf_counter)是我在工作中總結(jié)和整理出的一個(gè)庫,它的特點(diǎn)是在不干擾已有 SysTick 功能的前提下額外為我們提供系統(tǒng)周期測(cè)量的功能——并在這基礎(chǔ)上衍生出了 delay_us() 和 系統(tǒng)時(shí)間戳的功能——正可謂一鴨三吃,把SysTick榨干到了極致。perf_counter 庫的原理其實(shí)很簡單,但其中要處理的 corner case 確實(shí)很惱人,我也是歷經(jīng)一年多才真正想明白這里面的彎彎繞。后面如果閱讀量不錯(cuò)的話,我會(huì)考慮專門出一篇介紹 perf_counter 原理的文章。其中,關(guān)于如何“不影響現(xiàn)有SysTick中斷處理程序”的功能,已經(jīng)在之前的文章《【嵌入式秘術(shù)】手把手教你如何劫持RTOS》中進(jìn)行了詳細(xì)介紹,有興趣的小伙伴可以再回味回味。
在開源的過程中,為了簡化用戶的使用,我做了如下的優(yōu)化:
  • 在 Arm Compiler 5(armcc)和 Arm Compiler 6中,不需要用戶手工對(duì)庫進(jìn)行初始化——庫會(huì)在進(jìn)入main()之前“自己做”;

  • Lib中的perf_counter.lib適用于包含Cortex-M0在內(nèi)的全系列Cortex-M處理器,做到全覆蓋;

  • perf_counter.h 幾乎不依賴 之外的庫。使用.lib進(jìn)行部署,非常簡潔方便。


如果你要用 safe_atom_code(),則需要 __disable_irq() 和 __set_PRIMASK() 的定義,一般Cortex-M工程都有。這些定義是由 CMSIS提供的。一般來說,普通的 perf_counter 功能并不需要涉及任何這些內(nèi)容。


perf_counter庫的使用當(dāng)然也存在限制,重要的事情在最后說:
  • 如果你原本的 RTOS 使用了 SysTick并開啟了Tickless模式,perf_counter雖然不會(huì)干擾原有的 SysTick功能,但自己的計(jì)時(shí)功能卻會(huì)受到 Tickless模式的干擾;

  • perf_counter庫假設(shè)你原本的SysTick應(yīng)用會(huì)保持一個(gè)固定的定時(shí)周期——也就是 LOAD寄存器的內(nèi)容是固定的、不會(huì)隨著程序的執(zhí)行而經(jīng)常變化。其實(shí)RTOStickless模式會(huì)干擾perf_counter的計(jì)數(shù)可靠性也是這個(gè)原因



一般來說,大部分RTOS和普通的周期性定時(shí)功能都不會(huì)經(jīng)常動(dòng)態(tài)的去改變SysTick的計(jì)數(shù)周期,所以不必太擔(dān)心。

原創(chuàng)不易,如果你喜歡我的思維、覺得我的文章對(duì)你有所啟發(fā),

請(qǐng)務(wù)必 “點(diǎn)贊、收藏、轉(zhuǎn)發(fā)” 三連,這對(duì)我很重要!謝謝!


歡迎訂閱 裸機(jī)思維


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉