RM新时代网站-首页

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

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

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

RISC-V中一個(gè)優(yōu)化導(dǎo)致的問題案例

嵌入式USB開發(fā) ? 來源:嵌入式USB開發(fā) ? 作者:嵌入式USB開發(fā) ? 2023-06-08 10:02 ? 次閱讀

本文轉(zhuǎn)自公眾號(hào),歡迎關(guān)注

優(yōu)化導(dǎo)致的問題案例 (qq.com)

  • 一.過程
  • 二.思考

一.過程

關(guān)鍵代碼如下

通過串口驅(qū)動(dòng)接口,注冊串口接收回調(diào)函數(shù),uart_rx_callback

該回調(diào)函數(shù)中如果收到串口數(shù)據(jù),長度非0,則更新全局變量uart_rx_len

主循環(huán)中再檢查全局變量uart_rx_len,如果大于0說明收到了串口數(shù)據(jù),將收到的數(shù)據(jù)再發(fā)送出去,實(shí)現(xiàn)簡單的串口回環(huán)測試。

static int uart_rx_len = 0;
void uart_rx_callback(const void *buffer, uint32_t length)
{
    if(length >0)
    {
        uart_rx_len = length;
    }
}
int main(void)
{
    ......
    debug_uart_init(IOT_UART_PORT_1);
    uint8_t buffer[64];
    iot_uart_register_rx_callback(IOT_UART_PORT_1,buffer,sizeof(buffer),uart_rx_callback);
    while(1)
    {
        if(uart_rx_len > 0)
        {
            iot_uart_write_buffer(IOT_UART_PORT_1,buffer,uart_rx_len);
            uart_rx_len=0;
        }
    }
}

現(xiàn)象是并沒有實(shí)現(xiàn)上述回環(huán)測試的功能。

于是進(jìn)行調(diào)試,先確認(rèn)是否進(jìn)入了接收處理,

b uart_rx_callback

發(fā)現(xiàn)可以進(jìn)入該回調(diào)函數(shù),說明收到了數(shù)據(jù)。

step單步運(yùn)行到執(zhí)行完uart_rx_len = length;,再查看該變量的值

(gdb) p uart_rx_len
$2 = 1

也確實(shí)收到了一個(gè)字節(jié)。

然后繼續(xù)往下看,看如下條件是否進(jìn)入

if(uart_rx_len  > 0)
        {
            iot_uart_write_buffer(IOT_UART_PORT_1,buffer,uart_rx_len);
            uart_rx_len=0;
        }

b main.c:146iot_uart_write_buffer(IOT_UART_PORT_1,buffer,uart_rx_len所在行146行,打斷點(diǎn)。

發(fā)現(xiàn)進(jìn)不了該斷點(diǎn)。

這里就比較奇怪了,前面uart_rx_len確實(shí)是1,了但是這里條件卻進(jìn)不去,其他地方也沒有寫uart_rx_len的地方。

那么只有繼續(xù)看該處代碼對應(yīng)的匯編代碼

先在uart_rx_callback前打斷點(diǎn),串口接收一個(gè)字節(jié)觸發(fā)該回調(diào)執(zhí)行。再在 if(uart_rx_len > 0)所在的行144行前打斷點(diǎn),b main.c:144c運(yùn)行到該處。

此時(shí)看到uart_ex_len的值是1正確的。

(gdb) p uart_rx_len
$2 = 1

layout split打開匯編和C對照窗口。

查看變量uart_rx_len的地址,為0x20300c8

(gdb) p &uart_rx_len
$4 = (int *) 0x20300c8 < uart_rx_len >
(gdb) info reg s1
s1             0x2030000        33751040

S1寄存器的值設(shè)置為0x2030000, lui s1,0x2030 lui的u表示up(高20位),加載0x2030到S1的高20位。

lw a2,200(S1)即將S1對應(yīng)的地址偏移200(0xC8)地址處的值加載到a2寄存器。

正好是獲取0x2030C8(uart_rx_len)的值到A2,

然后再執(zhí)行

blez a2,0x20001ba進(jìn)行判斷uart_rx_len和0的值比較,判斷是否往下執(zhí)行還是在此死循環(huán)。

圖片

初看沒問題,一細(xì)看就有端倪了。

假設(shè)一開始uart_rx_len=0,

那么后面始終執(zhí)行的是一條語句,blez a2,0x20001ba,a2寄存器的值不再更新了,這就有問題了,內(nèi)存中0x2030C8(uart_rx_len)的值變了,但是寄存器a2的值不再變化。

這就是編譯器自作主張優(yōu)化,生成的代碼沒有繼續(xù)去從內(nèi)存0x2030C8(uart_rx_len)處更新值到a2寄存器了。理論上是需要再次執(zhí)行上述lw a2,200(S1)指令的。這就編譯器優(yōu)化導(dǎo)致的問題。

我們修改

static int uart_rx_len = 0;

改為

`static volatile int uart_rx_len = 0;``

再來看匯編代碼。

可以看到如果a5小于0,會(huì)跳轉(zhuǎn)到addi s1,s2,200處執(zhí)行再繼續(xù)lw a5,0(S1)處加載uart_rx_len的值到a5,會(huì)不斷從內(nèi)存處更新值到寄存器。

圖片

這就是volatile的作用,加了volatile后編譯器始終,會(huì)從內(nèi)存中更新值到寄存器,而不會(huì)自作主張使用寄存器中緩存的值。

默認(rèn)SCons/riscv_tools.py中是Os優(yōu)化,

CCFLAGS = common_flags + [
        "-Os",
    ]

不加volatile且優(yōu)化改為

-O3,-O2,-O1,-O0分別看一下。

可以看到-O1優(yōu)化編譯就進(jìn)行了優(yōu)化,后面-O2,-O3就不用看了。

-O0

圖片

-O1

圖片

二.思考

這里函數(shù)uart_rx_callback寫了變量uart_rx_len

void uart_rx_callback(const void *buffer, uint32_t length)
{
    if(length >0)
    {
        uart_rx_len = length;
    }
}

且uart_rx_callback函數(shù)也作為回調(diào)函數(shù)使用了,理論上編譯器應(yīng)該指導(dǎo)uart_rx_len會(huì)被改寫,不應(yīng)該作此優(yōu)化。

手動(dòng)調(diào)用以下uart_rx_callback

uart_rx_callback(0, 0);
    debug_uart_init(IOT_UART_PORT_1);

還是一樣的優(yōu)化了

圖片

看來編譯器還是聰明過頭了。

這里主要是

while(1)后面第一條語句就是判斷uart_rx_len,如果之前還有其他語句,則編譯器可能不會(huì)優(yōu)化了。

while(1)

    {

        if(uart_rx_len > 0)

        {

            iot_uart_write_buffer(IOT_UART_PORT_1,buffer,uart_rx_len);

            uart_rx_len=0;

        }

    }

圖片

審核編輯:湯梓紅

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

    關(guān)注

    5082

    文章

    19104

    瀏覽量

    304791
  • 串口
    +關(guān)注

    關(guān)注

    14

    文章

    1551

    瀏覽量

    76421
  • 優(yōu)化
    +關(guān)注

    關(guān)注

    0

    文章

    220

    瀏覽量

    23890
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4327

    瀏覽量

    62569
  • RISC-V
    +關(guān)注

    關(guān)注

    45

    文章

    2270

    瀏覽量

    46125
收藏 人收藏

    評論

    相關(guān)推薦

    rIsc-v的缺的是什么?

    態(tài)系統(tǒng)還不夠豐富。這可能導(dǎo)致軟件和工具的可用性受限,特別是在些特定的應(yīng)用領(lǐng)域或開發(fā)環(huán)境中。開發(fā)者可能需要投入更多的時(shí)間和精力來尋找或開發(fā)適合RISC-V架構(gòu)的軟件和工具鏈。 碎片化風(fēng)險(xiǎn):由于
    發(fā)表于 07-29 17:18

    risc-v的發(fā)展歷史

    RISC-V的發(fā)展歷史可以追溯到2006年左右,當(dāng)時(shí)David Patterson和其他研究者開始探索創(chuàng)建個(gè)開放和可擴(kuò)展的指令集架構(gòu)(ISA)。以下是RISC-V發(fā)展的主要里程碑:
    發(fā)表于 07-29 17:20

    關(guān)于RISC-V學(xué)習(xí)路線圖推薦

    個(gè)號(hào)的RISC-V學(xué)習(xí)路線圖可以幫助學(xué)習(xí)者系統(tǒng)地掌握RISC-V架構(gòu)的相關(guān)知識(shí)。比如以下是個(gè)
    發(fā)表于 11-30 15:21

    為什么選擇RISC-V?

    。例如,如果工程師在FPGA中實(shí)現(xiàn)軟RISC-V內(nèi)核,則通??梢允褂肦TL源代碼。由于RISC-V免版稅,這為將基于RISC-V的設(shè)計(jì)從FPGA移植到ASIC或另一個(gè)FPGA帶來了極大
    發(fā)表于 07-27 17:38

    如何設(shè)計(jì)個(gè)好的RISC-V

    文章目錄寫在前面什么是RISC-VRISC-V誕生的背景ISA霸權(quán)摩爾定律的窮途末路窮困潦倒的學(xué)者不斷增長的指令數(shù)量RISC-V架構(gòu)設(shè)計(jì)思想如何設(shè)計(jì)個(gè)好的ISARISC-
    發(fā)表于 07-26 06:42

    RISC-V MCU開發(fā)相關(guān)資料分享

    開發(fā)工作中。 工欲善其事必先利其器,要想實(shí)現(xiàn)基于RISC-V MCU的項(xiàng)目開發(fā),與之配套的集成開發(fā)環(huán)境必不可少。目前市場上可供選擇的RISC-V MCU開發(fā)工具已初具規(guī)模,由MounRiver團(tuán)隊(duì)打造的MounRiver? Studio(MRS)便是其
    發(fā)表于 11-10 07:50

    優(yōu)化的關(guān)鍵,RISC-V中的性能監(jiān)控

    RISC-V在云端、數(shù)據(jù)中心、汽車與網(wǎng)絡(luò)技術(shù)中的頻繁創(chuàng)新和亮相,已經(jīng)讓這成長中的ISA只腳邁入了高性能計(jì)算場景。然而缺少強(qiáng)大的性能監(jiān)測工具讓RISC-V的應(yīng)用
    發(fā)表于 12-27 08:00

    risc-v峰會(huì)亮點(diǎn) RT-Thread對RISC-V的支持

    在第RISC-V中國峰會(huì)上看點(diǎn)很多,我們來看看risc-v峰會(huì)其中一個(gè)非常重要的亮點(diǎn) ;RT-Thread對
    發(fā)表于 06-23 11:29 ?7847次閱讀
    <b class='flag-5'>risc-v</b>峰會(huì)亮點(diǎn) RT-Thread對<b class='flag-5'>RISC-V</b>的支持

    risc-v中國峰會(huì)直播:如何優(yōu)化RISC-V指令集架構(gòu)的代碼密度?

    屆中國峰會(huì)在上海舉辦,以下是小編整理的部分risc-v峰會(huì)的內(nèi)容。主要介紹了影響代碼密度的因素以及如何優(yōu)化RISC-V指令集架構(gòu)的代碼密度?感興趣的小伙伴可以詳細(xì)了解
    的頭像 發(fā)表于 06-23 12:12 ?3114次閱讀
    <b class='flag-5'>risc-v</b>中國峰會(huì)直播:如何<b class='flag-5'>優(yōu)化</b><b class='flag-5'>RISC-V</b>指令集架構(gòu)的代碼密度?

    RISC-V峰會(huì)看點(diǎn) RISC-V如何進(jìn)入服務(wù)器、高性能市場

    在第RISC-V中國峰會(huì)上看點(diǎn)很多,我們來看看risc-v峰會(huì)其中一個(gè)非常重要的亮點(diǎn) ;RISC-V
    發(fā)表于 06-23 14:14 ?8454次閱讀
    <b class='flag-5'>RISC-V</b>峰會(huì)看點(diǎn) <b class='flag-5'>RISC-V</b>如何進(jìn)入服務(wù)器、高性能市場

    RISC-V中國峰會(huì)看點(diǎn) risc-v開發(fā)要怎么優(yōu)化risc-v指令集架構(gòu)代碼密度

    在第RISC-V中國峰會(huì)上看點(diǎn)很多,RISC-V是開源的,那么代碼密度要怎么控制,會(huì)不會(huì)因?yàn)殚_源而導(dǎo)致代碼密度特別大? 我們起來看看
    發(fā)表于 06-23 18:22 ?9674次閱讀
    第<b class='flag-5'>一</b>屆<b class='flag-5'>RISC-V</b>中國峰會(huì)看點(diǎn) <b class='flag-5'>risc-v</b>開發(fā)要怎么<b class='flag-5'>優(yōu)化</b><b class='flag-5'>risc-v</b>指令集架構(gòu)代碼密度

    RISC-V,真的要上天了!

    X280,是個(gè)多核、多集群能力的 RISC-V處理器,提供了對RISC-V矢量擴(kuò)展標(biāo)準(zhǔn)和SiFive智能擴(kuò)展的全面支持,并針對邊緣的AI/ML計(jì)算進(jìn)行了
    的頭像 發(fā)表于 09-09 09:59 ?799次閱讀

    RISC-VRISC-V AI的未來(特邀講座)

    主題演講:RISC-VRISC-V AI的未來(特邀講座)ppt分享
    發(fā)表于 07-14 17:15 ?16次下載

    RISC-V生態(tài)強(qiáng)勁 RISC-V International會(huì)員超4000 超75個(gè)技術(shù)工作組

    的 4,000 多名成員,擁有超過 75 個(gè)技術(shù)工作組,推動(dòng) RISC-V 標(biāo)準(zhǔn)、軟件、工具等方面的進(jìn)展。僅今年年,RISC-V 就批準(zhǔn)了 12 項(xiàng)規(guī)范,還有更多規(guī)范即將批準(zhǔn)。此外,
    的頭像 發(fā)表于 11-09 15:17 ?761次閱讀

    RISC-V為何如此重要?

    本文由半導(dǎo)體產(chǎn)業(yè)縱橫(ID:ICVIEWS)編譯自xda-developersRISC-V正在緩慢而悄然地改變CPU市場。RISC-V在過去幾年中一直是行業(yè)流行語,它正在慢慢改變半導(dǎo)體市場。但是
    的頭像 發(fā)表于 04-29 08:28 ?381次閱讀
    <b class='flag-5'>RISC-V</b>為何如此重要?
    RM新时代网站-首页